美文网首页Kotlin基础学习
Kotlin中的延迟属性(lazy properties)

Kotlin中的延迟属性(lazy properties)

作者: deep_sadness | 来源:发表于2017-08-29 15:50 被阅读685次

    属于Kotlin中的委托属性这一章中的标准委托

    延迟属性Lazy

    lazy() 是接受一个lambda 并返回一个 Lazy <T> 实例的函数,返回的实例可以作为实现延迟属性的委托。也就是说:
    第一次调用get() 会执行已传递给 lazy() 的 lambda 表达式并记录结果, 后续调用get() 只是返回记录的结果。

    这里需要注意的是 调用的是 get()方法,和set没啥关系

    val lazyValue: String by lazy {
        println("computed!")
        "Hello"
    }
    
    fun main(args: Array<String>) {
        println(lazyValue)
        println(lazyValue)
    }
    

    输出结果为

    computed!
    Hello
    Hello
    

    同步锁模式

    防止对个线程同时初始化

    默认情况下,对于 lazy 属性的求值是同步锁的(synchronized):该值只在一个线程中计算,并且所有线程会看到相同的值。如果初始化委托的同步锁不是必需的,这样多个线程可以同时执行,那么将 LazyThreadSafetyMode.PUBLICATION 作为参数传递给 lazy() 函数。 而如果你确定初始化将总是发生在单个线程,那么你可以使用 LazyThreadSafetyMode.NONE模式, 它不会有任何线程安全的保证和相关的开销。

    延迟属性Lazy 与 lateinit 区别

    以下是lateinit var和by lazy { ... }委托属性之间的显著差异:

    • lazy { ... }代表只能用于val属性,而lateinit只能用于var,因为它不能编译到final字段,因此不能保证不变性;
    • lateinit var具有存储值的后备字段(backing field),而by lazy { ... }创建一个委托对象,其中存储一次计算的值,将对代理实例的引用存储在类对象中,并为与委托实例一起使用的属性生成getter。
    • 除了val之外,lateinit不能用于可空属性和Java原语类型(这是因为null用于未初始化的值);所以如果你需要在类中存在的支持字段,请使用lateinit;
      lateinit var可以从对象被看到的任何地方被初始化。从一个框架代码的内部,多个初始化方案是可能的单一类的不同对象。 by lazy { ... }反过来又定义了属性的唯一初始化器,只能通过覆盖子类中的属性进行更改。如果您希望以预先未知的方式从外部初始化属性,请使用lateinit。
    • 另外,还有一个方法没有提到Delegates.notNull(),它适用于non-null属性的延迟初始化,包括Java原始类型的属性。

    延迟属性Lazy 与 lateinit 使用总结

    lateinit用于外部初始化:当需要外部资料通过调用方法初始化您的值时。
    例如通过调用:

    private lateinit var value: MyClass
    
    fun init(externalProperties: Any) {
       value = somethingThatDependsOn(externalProperties)
    }
    

    lazy当它只使用对象内部的依赖关系时。
    嗯。静态变量的初始化挺适合这种方式的。

    相关文章

      网友评论

        本文标题:Kotlin中的延迟属性(lazy properties)

        本文链接:https://www.haomeiwen.com/subject/gbnodxtx.html