【kotlin】延迟初始化:lateinit与by lazy{ ... }的区别

  • by lazy { ... }
    只能被用在被val修饰的变量上,
    而lateinit只能被用var修饰的变量上,
    因为被lateinit修饰的字段无法被编译为一个final字段、
    因此无法保证它的不可变性。

  • 被lateinit修饰的变量有一个幕后字段用来存储它的值,
    而by lazy { ... }创建了一个包含by lazy { ... }中代码返回值的实例对象,
    实例对象持有这个值并生成一个可以在实例对象中调用的这个值的getter。
    所以如果你需要在代码中使用幕后字段的话,
    使用lateinit

  • 除了被val修饰的变量外,
    lateinit也不能被用来修饰可空的属性和java的基本类型
    (因为对于可空类型,会有默认值null)

  • 被lateinit修饰的变量可以在对象(代码)的任何地方进行初始化,
    而且同一个类的不同对象可以对这个变量进行多次的初始化(赋值)。
    但是,
    对于by lazy { ... }修饰的变量,
    只拥有唯一一个声明在{}中的初始化构造器,
    如果你想要修改它,
    你只能通过在子类中覆写的方式来修改它的值。
    所以,
    如果你想要你的属性在其他地方以不是你事先定义好的值初始化的话,
    使用lateinit

  • by lazy { ... }的初始化默认是线程安全的,
    并且能保证by lazy { ... }代码块中的代码最多被调用一次。
    而lateinit var默认是不保证线程安全的,
    它的情况完全取决于使用者的代码。

  • Lazy实例是有值的,
    这个值可以被存储、
    传递和使用。
    但是,
    被lateinit var修饰的变量不存储任何多余的运行时状态,
    只有值还未被初始化的null值。

  • 如果你持有一个Lazy实例的引用,
    你可以使用它的isInitialized()方法来判断它是否已经被初始化。
    从Kotlin1.2开始,
    你也可以使用方法引用的方式来获取这个值。

  • by lazy { ... }
    中传递的lambda表达式可能会捕获它的闭包中使用的上下文的引用,
    引用会一直被持有直到变量被初始化。
    因此这样可能会导致内存泄漏,
    所以仔细考虑你在lambda表达式中使用的值是否合理

资料来源:https://stackoverflow.com/questions/36623177/kotlin-property-initialization-using-by-lazy-vs-lateinit

posted @ 2021-01-04 10:34  ClearMoon  阅读(663)  评论(0)    收藏  举报