在Kotlin中,如果你不想在构造函数内部或类主体顶部初始化一个类属性,你基本上有以下两个选项(来自语言引用):

延迟初始化

lazy()是一个接受lambda并返回lazy <T>实例的函数,它可以作为实现lazy属性的委托:第一次调用get()执行传递给lazy()的lambda并记住结果,后续调用get()只返回记住的结果。 例子 公共类Hello { val myLazyString:通过lazy {"Hello"} }

第一个调用和随后的调用,不管它在哪里,对myLazyString都会返回Hello

晚些时候初始化

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: public class MyTest { lateinit var subject: TestSubject @SetUp fun setup() { subject = TestSubject() } @Test fun test() { subject.method() } } The modifier can only be used on var properties declared inside the body of a class (not in the primary constructor), and only when the property does not have a custom getter or setter. The type of the property must be non-null, and it must not be a primitive type.

那么,既然这两种方法都能解决同一个问题,如何在这两种方法中正确选择呢?


当前回答

除了热键的好答案之外,下面是我在实践中如何在这两个选项中进行选择:

Lateinit用于外部初始化:当你需要通过调用一个方法来初始化你的值时。

例如,通过呼叫:

private lateinit var value: MyClass

fun init(externalProperties: Any) {
   value = somethingThatDependsOn(externalProperties)
}

lazy是指它只使用对象内部的依赖关系。

其他回答

除了这些很棒的答案,还有一个概念叫做惰性加载:

延迟加载是计算机编程中常用的一种设计模式,用于将对象的初始化推迟到需要它的时候。

正确使用它,可以减少应用程序的加载时间。Kotlin的实现方式是lazy(),它在需要的时候将所需的值加载到变量中。

但是lateinit是当你确定一个变量不是空的或者是空的,并且在你使用它之前会被初始化——例如在android的onResume()方法中——所以你不想将它声明为可空类型。

Lateinit vs lazy

lateinit i)与可变变量[var]一起使用 lateinit var name: String //允许 lateinit val name: String //不允许

ii)只允许使用非空数据类型

    lateinit var name: String       //Allowed
    lateinit var name: String?      //Not Allowed

iii)这是对编译器的一个承诺,该值将在未来被初始化。

注意:如果你试图访问lateinit变量而没有初始化它,那么它会抛出UnInitializedPropertyAccessException异常。

懒惰的 i)延迟初始化是为了防止不必要的对象初始化。

ii)你的属性不会被初始化,除非你使用它。

iii)只初始化一次。下次使用它时,将从缓存中获取值。

iv)它是线程安全的(它在第一次使用的线程中初始化。其他线程使用缓存中存储的相同值)。

v)该属性只能为val。

vi)属性可以是任何类型(包括基本类型和空值,这是lateinit不允许的)。

如果您正在使用Spring容器,并且希望初始化不可空的bean字段,lateinit更适合。

    @Autowired
    lateinit var myBean: MyBean

顺便说一下lateinit和lazy

后期

仅用于可变变量,即var和非空数据类型

lateinit var name: String //允许为非空

你是在告诉编译器这个值将来会被初始化。

注意:如果你试图访问lateinit变量而没有初始化它,那么它会抛出UnInitializedPropertyAccessException异常。

lazy

延迟初始化是为了防止不必要的对象初始化。 除非你使用你的变量,否则它不会被初始化。 它只初始化一次。下次使用它时,将从缓存中获取值。 它是线程安全的。 变量只能为val且不可为空。

欢呼:)

除了热键的好答案之外,下面是我在实践中如何在这两个选项中进行选择:

Lateinit用于外部初始化:当你需要通过调用一个方法来初始化你的值时。

例如,通过呼叫:

private lateinit var value: MyClass

fun init(externalProperties: Any) {
   value = somethingThatDependsOn(externalProperties)
}

lazy是指它只使用对象内部的依赖关系。