转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/93764289
本文出自【赵彦军的博客】


高阶函数

  • lateinit 延迟初始化
  • lazy 延迟初始化
  • lazy 延迟模式
  • 总结

Koltin中属性在声明的同时也要求要被初始化,否则会报错。例如以下代码:

private var name0: String //报错
private var name1: String = "xiaoming" //不报错
private var name2: String? = null //不报错

可是有的时候,我并不想声明一个类型可空的对象,而且我也没办法在对象一声明的时候就为它初始化,那么这时就需要用到Kotlin提供的延迟初始化。Kotlin中有两种延迟初始化的方式。一种是 lateinit var,一种是by lazy

lateinit 延迟初始化

private lateinit var name: String
  • lateinit var只能用来修饰类属性,不能用来修饰局部变量,并且只能用来修饰对象,不能用来修饰基本类型(因为基本类型的属性在类加载后的准备阶段都会被初始化为默认值)。
  • lateinit var的作用也比较简单,就是让编译期在检查时不要因为属性变量未被初始化而报错。
  • Kotlin相信当开发者显式使用lateinit var关键字的时候,他一定也会在后面某个合理的时机将该属性对象初始化的.

lateinitAndroid中使用

class MainActivity : AppCompatActivity() {private lateinit var bt: Buttonoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)bt = findViewById(R.id.bt)bt.setOnClickListener {Toast.makeText(baseContext, "click", Toast.LENGTH_SHORT).show()}}
}

lazy 延迟初始化

by lazy本身是一种属性委托。属性委托的关键字是byby lazy的写法如下:

//用于属性延迟初始化
val name: Int by lazy { 1 }//用于局部变量延迟初始化
public fun foo() {val bar by lazy { "hello" }println(bar)
}
  • by lazy要求属性声明为val,即不可变变量,在java中相当于被final修饰。这意味着该变量一旦初始化后就不允许再被修改值了(基本类型是值不能被修改,对象类型是引用不能被修改)。{}内的操作就是返回唯一一次初始化的结果。
  • by lazy可以使用于类属性或者局部变量。

在 Android 中使用

class MainActivity : AppCompatActivity() {private val bt by lazy {findViewById<Button>(R.id.bt)}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)bt.setOnClickListener {Toast.makeText(baseContext, "click", Toast.LENGTH_SHORT).show()}}
}

lazy 延迟模式

在使用 lazy 延迟初始化的时候,Kotlin提供了3中模式,源码如下:

public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =when (mode) {LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)}
  • 模式1: LazyThreadSafetyMode.SYNCHRONIZED
    线程安全模式,Initializer函数只能被调用一次,返回的对象只有一个

  • 模式2:LazyThreadSafetyMode.PUBLICATION
    在对未初始化的[Lazy]实例值进行并发访问时,可以多次调用Initializer函数,但只有第一个返回值将用作[Lazy]实例的值。

  • 模式3:LazyThreadSafetyMode.NONE
    没有锁用于同步对[Lazy]实例值的访问; 如果从多个线程访问实例,可能会有多个实例。除非保证[Lazy]实例永远不会从多个线程初始化,否则不应使用此模式。

当我们模式都不用的情况下,默认使用 LazyThreadSafetyMode.SYNCHRONIZED 线程安全模式。源码如下:

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

几个例子,使用延迟模式创建一个单例

class Manager {init {Log.e("zhaoyanjun:inin", "初始化")}companion object {val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {Manager()}}
}

总结

那么,再总结一下,lateinit varby lazy哪个更好用?
首先两者的应用场景是略有不同的。然后,虽然两者都可以推迟属性初始化的时间,但是lateinit var只是让编译期忽略对属性未初始化的检查,后续在哪里以及何时初始化还需要开发者自己决定。

by lazy真正做到了声明的同时也指定了延迟初始化时的行为,在属性被第一次被使用的时候能自动初始化。但这些功能是要为此付出一丢丢代价的。


个人微信号:zhaoyanjun125 , 欢迎关注

Kotlin实战指南九:延迟初始化相关推荐

  1. Kotlin实战指南十九:use 函数魔法

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/117366756 本文出自[赵彦军的博客] 文章目录 往期精彩文章 use函数 往期 ...

  2. Kotlin实战指南二十:flow

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/117370700 本文出自[赵彦军的博客] 文章目录 往期精彩文章 flow 是啥 ...

  3. Kotlin实战指南十八:open、internal 关键字使用

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/117365712 本文出自[赵彦军的博客] 文章目录 往期精彩文章 open关键字 ...

  4. Kotlin实战指南十七:JvmField、JvmStatic使用

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/116668666 本文出自[赵彦军的博客] 文章目录 往期精彩文章 @JvmFiel ...

  5. Kotlin实战指南十:let、apply、with、run

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details//94402604 本文出自[赵彦军的博客] 文章目录 let 示例1:基础用法 示 ...

  6. Kotlin实战指南七:单例模式

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/87941461 本文出自[赵彦军的博客] 单例模式 无参单例模式-线程安全 懒加载 ...

  7. Kotlin实战指南五:继承、接口

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/87874895 本文出自[赵彦军的博客] 继承.接口 继承 子类有主构造函数 子类 ...

  8. Kotlin实战指南十六:Synchronized、Volatile

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/116267707 本文出自[赵彦军的博客] 文章目录 如何创建线程 Thread 如 ...

  9. Kotlin实战指南十四:协程启动模式

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/96008400 本文出自[赵彦军的博客] 文章目录 协程启动 DEFAULT LA ...

最新文章

  1. Roundgod and Milk Tea 贪心
  2. 例6.12(Java)
  3. Datatables中文API——回调函数
  4. 算法导论读书笔记 第4章 分治策略
  5. 应用程序的8个关键性能指标以及测量方法
  6. grails框架_Play和Grails Java框架的优缺点
  7. Linu系统编程---10(Linux的终端,线路规程,网络终端,进程组)
  8. 20154319 《网络对抗技术》后门原理与实践
  9. 【Java】获取并打印当前堆栈的方法
  10. java机器PDF_机器人制作入门(第3版)PDF 下载
  11. oracle dba create view 失败 解决办法
  12. poj 2182 给你每个数前面有几个数比他小让你输出次数的编号
  13. c语言图书管理系统出现的问题,C语言图书管理系统中的问题
  14. 当前应用拦截NFC响应,不弹出选择框教程
  15. div和span的标签属性及说明
  16. 云计算:细分之七大类商业模式
  17. 【图论】图的定义和术语
  18. Mybatis-Plus代码生成器CodeGenerator
  19. spring启动之xml
  20. 薪酬福利管理太复杂?有实在RPA就够了

热门文章

  1. f12 卡 谷歌浏览器_干货分享。关于谷歌浏览器的使用技巧,不需要插件
  2. c mysql批量添加数据类型_mybatis学习之路----mysql批量新增数据
  3. php隐藏表单提交表单提交表单_表单提交及php处理表单数据的实例
  4. c语言中的typedef struct相当于java的一个类?,C ++中'struct'和'typedef struct'之间的区别?...
  5. 4个Keynote、12篇论文分享、40个Poster,CVPR 2021论文分享会全日程公布
  6. Transformer升级之路:Sinusoidal位置编码追根溯源
  7. Word Embedding List|ACL 2020 词嵌入长文汇总及分类
  8. T-GANs:基于“图灵测试”的生成对抗模型
  9. 活动 | INTERFACE#4 解读搜狗机器翻译技术,体验搜狗旅行翻译宝产品
  10. 揭秘阿里小蜜:基于检索模型和生成模型相结合的聊天引擎 | PaperDaily #25