为什么后期初始化变量不能与 Nullable 一起使用?



为什么我们不能将lateinit与可为空的变量一起使用?

lateinit var v: String?

不允许对可为 null 类型的属性使用lateinit修饰符

lateinit仅用于避免将来的空检查,这就是为什么不允许在可为空类型的属性上使用lateinit修饰符的原因。

如果您希望它nullable那么您可以像var b: String? = null一样简单地使用

如果你想创建一个可为空类型的变量,那么你不需要后期初始化。文档说

通常,声明为具有非 null 类型的属性必须在构造函数中初始化。 但是,这通常不方便。例如,可以通过以下方式初始化属性 依赖关系注入,或在单元测试的设置方法中。在这种情况下,不能提供非空 构造函数中的初始值设定项,但您仍然希望在引用 类主体中的属性。

因此,当您打算在构造函数中的某个地方初始化变量并且还希望避免空检查时,将使用 lateinit。

如文档中所述,lateinit专门研究不可为空的属性:

通常,声明为具有非 null类型的属性必须在构造函数中初始化。但是,这通常不方便。例如,可以通过依赖项注入或在单元测试的设置方法中初始化属性。在这种情况下,不能在构造函数中提供null 初始值设定项,但仍希望在引用类主体中的属性时避免 null 检查

此外,如果您查看此类lateinit属性的字节代码,您会看到编译器添加了一个代码块,以确保此属性在访问时已初始化。对于lateinit属性,null指示属性的初始但无效状态。

class WithLateInit {
lateinit var something : String
}

成为

public final class WithLateInit {
@NotNull
public String something;
@NotNull
public final String getSomething() {
String var10000 = this.something;
if (var10000 == null) { // <- here you can see the lateinit check
Intrinsics.throwUninitializedPropertyAccessException("something");
}
return var10000;
}
//setter
}

Kotlin 的类型系统旨在消除代码中空引用的危险

所以两者都代表妥协。使用lateinit可以确保变量最终初始化为非空。如果甚至不能保证这一点,则可以使用可为空。

通常,声明为具有非 null 类型的属性必须是 在构造函数中初始化。然而,这往往不是 方便。

例如,可以通过依赖项初始化属性 注入,或在单元测试的设置方法中。在这种情况下,您 无法在构造函数中提供非 null 初始值设定项,但 在引用属性时仍希望避免空检查在类的主体内。

若要处理这种情况,可以使用lateinit标记属性 修饰语。

这就是为什么它不支持

因此,如果您将任何var指定为lateinit,这意味着编译器只需忽略它进行初始化并将其标记为在不久的将来初始化的非 null 类型,这就是为什么它不支持 nullable类型以避免运行时歧义。

kotlin 的主要功能之一是 Null Safe。

默认情况下,它不允许您创建空值。您已经明确定义了
var a: String? = null
,如果您不想初始化变量的任何值,则会出现"lateinit"。使用 lateinit 变量时,您会预先检查它是否已初始化

最新更新