为什么 late init var 不能与 Nullable 一起使用?

Why late init var cannot be used with Nullable?

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

lateinit var v: String?

lateinit 修饰符不允许用于可空类型的属性

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

如果你想让它成为 nullable 那么你可以简单地使用 var b: String? = null

Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient.

For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class.

To handle this case, you can mark the property with the lateinit modifier.

所以不支持 null.

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

Kotlin's type system is aimed at eliminating the danger of null references from code

所以两者都代表妥协。随着 lateinit you ensure that the variable will eventually be initialized to non-null. If you cannot even guarantee that, you can use nullable.

如果你想创建一个可为 null 类型的变量,那么你不需要 late init 。医生说

Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient. For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a nonnull initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class.

因此,当您打算在不在构造函数中的某处初始化变量并且还想避免空检查时,可以使用 late init。

kotlin 的主要特性之一是 Null 安全。

默认情况下不允许您创建空值。您已明确定义
var a: String? = null
,如果你不想初始化变量的任何值,那么 "lateinit"。在使用 lateinit 变量时你做 pre-check 无论它是否被初始化

如文档中所述,lateinit 专注于 non-nullable 属性:

Normally, properties declared as having a non-null type must be initialized in the constructor. However, fairly often this is not convenient. For example, properties can be initialized through dependency injection, or in the setup method of a unit test. In this case, you cannot supply a non-null initializer in the constructor, but you still want to avoid null checks when referencing the property inside the body of a class.

另外,如果你看一下这样一个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
}