我正在尝试一些 Android 的东西并在途中学习 Kotlin,我想知道如何初始化视图和属性。
据我了解,Kotlin 和 Java 中的契约(“我将在使用前初始化”)以及 UninitializedPropertyAccessException 和 NullPointerException 或多或少是等效的。在这两种情况下,您都可以进行 isInitialized 检查。我只是不知道为什么 JetBrains 会如此费心于空安全,然后以不同的形式引入完全相同的东西。
那么,lateinit 有什么优势吗?
示例代码:
public class Foo {
private String bar = null;
public void bar123() {
if (bar == null) {
bar = "bar";
}
}
}
Run Code Online (Sandbox Code Playgroud)
对比
class Foo {
private lateinit var bar: String
fun bar123() {
if (!::bar.isInitialized) {
bar = "bar"
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个想法是让编译器知道该属性是不可为空的,尽管它稍后会被初始化。这将减少在接收器代码中对该属性的空检查。
class Foo {
lateinit var prop: String
}
class Bar {
var prop: String? = null
}
fun consumeNotNull(arg: String) {
println(arg)
}
fun main() {
val foo = Foo()
consumeNotNull(foo.prop) // OK
val bar = Bar()
consumeNotNull(bar.prop) // Error: Type mismatch: inferred type is String? but String was expected
consumeNotNull(bar.prop!!) // OK
}
Run Code Online (Sandbox Code Playgroud)
想象一下,bar.prop在N个地方被引用。然后在每个地方你都必须对它“尖叫” ( bar.prop!!) 以使编译器满意。lateinit机制可让您避免这种情况并更加“安静”:) (并使您的代码更干净)
当然,如果Foo::prop在运行时使用它的时候没有初始化,你会得到异常:
UninitializedPropertyAccessException:lateinit 属性道具尚未初始化
但与 NullPointerException 相比,它更具描述性。