kotlin易混淆操作符
- 操作符?
- 如果要允许为空,我们可以声明一个变量为可空字符串,写作 String?
1 | var b: String? = "abc" |
- 安全调用操作符 ?
1 | val a = "Kotlin" |
以上结果
1
2
3null
6
如果 b 非空,就返回 b.length,否则返回 null,这个表达式的类型是 Int?。安全调用在链式调用中很有用。例如,如果一个员工 Bob 可能会(或者不会)分配给一个部门, 并且可能有另外一个员工是该部门的负责人,那么获取 Bob 所在部门负责人(如果有的话)的名字,我们写作:
1 | bob?.department?.head?.name |
- 操作符!!
第三种选择是为 NPE 爱好者准备的:非空断言运算符(!!)将任何值转换为非空类型,若该值为空则抛出异常。我们可以写 b!! ,这会返回一个非空的 b 值 (例如:在我们例子中的 String)或者如果 b 为空,就会抛出一个 NPE 异常:
1 | val l = b!!.length |
- 安全的类型转换
- 如果对象不是目标类型,那么常规类型转换可能会导致 ClassCastException。 另一个选择是使用安全的类型转换,如果尝试转换不成功则返回 null:
1 | val aInt: Int? = a as? Int |
取值方法(Getter)与设值方法(Setter)
1 | var <propertyName>[: <PropertyType>] [= <property_initializer>] |
其中的初始化器(initializer), 取值方法(getter), 以及设值方法(setter)都是可选的. 如果属性类型可以通过初始化器自动推断得到, (或者可以通过取值方法的返回值类型推断得到, 详情见下文), 则属性类型的声明也可以省略.
如果我们定义一个自定义取值方法(Getter), 那么每次读取属性值时都会调用这个方法(因此我们可以用这种方式实现一个计算得到的属性). 下面是一个自定义取值方法的示例:
1 | val isEmpty: Boolean |
field的使用
- 幕后属性或幕后字段。在Kotlin语言中,如果在类中定义一个成员变量,Kotlin将自动生成默认setter/getter方法。而Kotlin提供了一种非常特殊的方式声明setter/getter方法:
1 | var name: String? = null |
- field是当前属性的影子,就是当前的值this,setter/getter方法中使用。
kotlin in/out泛型中使用
- 父类泛型对象可以赋值给子类泛型对象,用 in,子类泛型对象可以赋值给父类泛型对象,用 out。
- 如果你的类是将泛型作为内部方法的返回,那么可以用 out:
1 | interface Production<out T> { |
- In(逆变)
1 | 如果你的类是将泛型对象作为函数的参数,那么可以用 in: |
- Invariant(不变)
- 如果既将泛型作为函数参数,又将泛型作为函数的输出,那就既不用 in 或 out。
1
2
3
4interface ProductionConsumer<T> {
fun produce(): T
fun consume(item: T)
}