Kotlin-6.1学习笔记

290 阅读4分钟

1、安全调用运算符: “?.”

它允许你把一次null检查和一次方法调用合并成一个操作。

如:

s?.toUpperCase()

等效于:

if(s != null) s.toUpperCase()
else null


2、Elvis运算符: “?:”

Elvis运算符(或者null合并运算符)

Elvis运算符接收两个运算数,如果第一个运算数不为null,运算结果就是抵押给运算数;否则,运算结果就是第二个运算数。

foo ?= bar

变换如下:

foo != null -> foo
foo == null -> bar


3、安全转换:"as?"

用于数据类型的常规Kotlin运算符:as运算符。

as?运算符尝试把值转换为指定的类型,如果值不是合适的类型就返回null,如下

foo as? Type

变换如下:

foo is Type -> foo as Type
foo !is Type -> null


4、非空断言:"!!"

非空断言是Kotlin提供给你的最简单直率的处理可空类型值的工具。

它使用双感叹号表示,可以把任何值转换成非空类型。

如果对null值做非空断言,则会抛出异常。

foo!!

转换如下

foo != null  -> foo
foo == null -> NullPointerException


注意:使用"!!"并且它的结果是异常时,异常调用栈的跟踪信息值表明异常发生在哪一行代码,而不会表明异常发生在哪一个表达式。为了让跟踪信息更清晰精确地表示哪个值为null,最好避免在同一行中使用多个"!!"断言


5、"let"函数

let函数让处理可空表达式变得更容易。

和安全调用运算符一起,它允许你对表达式求值,检查求值结果是否为null,并把结果保存为一个变量。

foo?.let {
...it...
}

转换如下:

foo != null 在lambda内部it是非空的
foo == null 什么都不会发生


6、延迟初始化的属性

使用lateinit修饰符来完成这样的声明:

如下:

class MyService{
    fun performAction(): String = "foo"
}

class MyTest{
    private lateinit var myService: MyService
    
    fun setUp(){
        myService = MyService()
    }
    
    fun testAction(){
        Objects.equals("foo",
                myService.performAction())
    }
}

注意:延迟初始化的属性都是var,因为需要在构造方法外修改它的值,而val属性会被编译成必须在构造方法中初始化的final字段。

注意:lateinit属性常见的一种用法是依赖注入。在这种情况下,lateinit属性的值是被依赖注入框架从外部设置的。


7、可空类性的扩展

Kotlin标准库中定义的String的两个扩展函数isEmptyisBlank就是这样的例子。

第一个函数判断字符串是否是一个空的字符串“”;

第二个则判断它是否是空或者它只包含空白字符。

因而就有isEmptyOrNullisNullOrBlank就可以由String?类型的接受者调用。


8、data class作用

在Kotlin中,无需手写一个JavaBean,可以直接使用data class,使用data class后编译器会自动生成如下方法

equals()
hashCode()
toString()
componentN()
copy()

注意数据类的前提条件:

  • 主构造方法至少要有一个参数
  • 所有的主构造方法参数都需要被标记为var或val
  • 数据类不能是抽象类、open类、sealed类(密封类)、inner类

数据类的定义示例:

data class Person(val name: String, var age: Int, var address: String)

数据类的使用:

fun main(){
     var person = Person("yang", 26, "hubei")
     println(person)
}

方法说明:

  • copy()

copy():作用在赋值时,很方便

在Java中,一个对象的类成员如果被另一个对象复制,仅仅修改了一个参数,那么需要把这个对象的所有值都赋值给另外一个对象,这样非常麻烦

在kotlin中,可以通过copy()方法执行修改某个参数

注意:如果不加参数名字,那么默认是第一个,否则必须明确参数名


图片来源:kotlin语言学习11 ——kotlin的data class(数据类)

  • 2. componentN()

componentN的方法主要在于,解构声明

  • 解构:在主构造方法中有多少个参数就会生成多少个component方法
  • 这些方法返回对应字段的值,component方法时用来实现解构声明的


补充

什么是解构声明?

在kotlin中可以把一个对象复制给多个变量,这种操作叫做解构声明(Destructuring declaration)。

先看如下例子:

data class Book(var name: String, var price: Float)

fun main(args: Array<String>) {
    val (name, price) = Book("Kotlin入门", 66.6f)
    println(name)
    println(price)
}
// 输出
Kotlin入门
66.6

我们定义了一个简单的数据类(data class),name、price变量分别输出了对应的属性值,大大简化了我们的操作!

数据类之所以可以使用解构声明,是由于数据类比较特殊,编译器默认为它声明了类似的函数:

    operator fun component1(): String {
        return name
    }

    operator fun component2(): Float {
        return price
    }

name、price变量赋值相当于分别调用了Book对象component1()、component2()函数,也就是解构的核心原理