lateinit是许多刚进入学习kotlin常常会掉入的坑之一。很多人为了保证java原有的语法,在定义变量和对象的过程中,会使用如下的定义方式。
class Demo{
private var value: String
fun printValue(){
println(value)
}
}
这个时候,编译器就会提示错误
Error:(2, 5) Kotlin: Property must be initialized or be abstract
然后有很多小伙伴解决问题,会使用提示符快捷键按钮自动修复这个问题,结果发现在定义变量的位置多了一个lateinit关键字
private lateinit var value: String
编译器的问题就这样躲避过去了,可是运行的过程,还是发生了异常问题。
lateinit修饰属性的时候,实际上就是表示,这个属性初始化的时机和方式,由开发者自己决定。而编译器在编译kotlin语言的过程中,会将lateinit修饰属性的所有调用位置都做一个非空的检查判断,然后抛出异常。 // 字节码等价代码
fun printValue() {
val tempValue = this.value
if(tempValue == null) {
throw UninitializedPropertyAccessException("lateinit property value has not been initialized")
}
println(tempValue)
}
你定义value属性的值确实为null,但由于给定value的类型为String类型,而kotlin当中String类型是不允许容纳null,kotlin为了保证“绝对的空安全性”,所以只能抛出异常。
对于 Kotlin 新手来说,应该抛开 Java 式的写法,牢记类属性的三种初始化方式:
- 主构造函数内定义属性,使用传入的参数初始化属性;
- 类体内定义属性,同时初始化;
- 类体内定义属性,init 块里初始化。
其他的初始化方式,慎用。
|