使用“by lazy”与“lateinit”进行属性初始化 - Property initialization using "by lazy" vs. "lateinit"

2021年11月20日 阅读数:4
这篇文章主要向大家介绍使用“by lazy”与“lateinit”进行属性初始化 - Property initialization using "by lazy" vs. "lateinit",主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

问题:

In Kotlin, if you don't want to initialize a class property inside the constructor or in the top of the class body, you have basically these two options (from the language reference):在 Kotlin 中,若是您不想在构造函数内部或类主体顶部初始化类属性,则基本上有如下两个选项(来自语言参考):html

  1. Lazy Initialization 延迟初始化

lazy() is a function that takes a lambda and returns an instance of Lazy<T> which can serve as a delegate for implementing a lazy property: the first call to get() executes the lambda passed to lazy() and remembers the result, subsequent calls to get() simply return the remembered result. lazy()是一个函数,它接受一个 lambda 并返回一个Lazy<T>的实例,它能够做为实现惰性属性的委托:对get()的第一次调用执行传递给lazy()的 lambda 并记住结果,随后对get()调用仅返回记住的结果。ide

Example例子函数

public class Hello { val myLazyString: String by lazy { "Hello" } }

So, the first call and the subsequential calls, wherever it is, to myLazyString will return Hello所以,不管在何处,对myLazyString的第一次调用和后续调用myLazyString将返回Hello单元测试

  1. Late Initialization 延迟初始化

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.例如,能够经过依赖注入或在单元测试的 setup 方法中初始化属性。 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.在这种状况下,您不能在构造函数中提供非 null 初始值设定项,但您仍然但愿在引用类体内的属性时避免空检查。测试

To handle this case, you can mark the property with the lateinit modifier:要处理这种状况,您能够使用 lateinit 修饰符标记该属性:this

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.修饰符只能用于在类的主体内(而不是在主构造函数中)声明的 var 属性,而且仅当该属性没有自定义 getter 或 setter 时。 The type of the property must be non-null, and it must not be a primitive type.属性的类型必须是非空的,而且不能是原始类型。url

So, how to choose correctly between these two options, since both of them can solve the same problem?那么,既然这两个选项均可以解决一样的问题,那么如何在这两个选项之间进行正确的选择呢?spa


解决方案:

参考: https://stackoom.com/en/question/2TfMP