Kotlin实战指南九:延迟初始化
转载请标明出处: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
关键字的时候,他一定也会在后面某个合理的时机将该属性对象初始化的.
lateinit
在Android
中使用
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
本身是一种属性委托。属性委托的关键字是by
。by 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 var
和by lazy
哪个更好用?
首先两者的应用场景是略有不同的。然后,虽然两者都可以推迟属性初始化的时间,但是lateinit var
只是让编译期忽略对属性未初始化的检查,后续在哪里以及何时初始化还需要开发者自己决定。
而by lazy
真正做到了声明的同时也指定了延迟初始化时的行为,在属性被第一次被使用的时候能自动初始化。但这些功能是要为此付出一丢丢代价的。
个人微信号:zhaoyanjun125 , 欢迎关注
Kotlin实战指南九:延迟初始化相关推荐
- Kotlin实战指南十九:use 函数魔法
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/117366756 本文出自[赵彦军的博客] 文章目录 往期精彩文章 use函数 往期 ...
- Kotlin实战指南二十:flow
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/117370700 本文出自[赵彦军的博客] 文章目录 往期精彩文章 flow 是啥 ...
- Kotlin实战指南十八:open、internal 关键字使用
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/117365712 本文出自[赵彦军的博客] 文章目录 往期精彩文章 open关键字 ...
- Kotlin实战指南十七:JvmField、JvmStatic使用
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/116668666 本文出自[赵彦军的博客] 文章目录 往期精彩文章 @JvmFiel ...
- Kotlin实战指南十:let、apply、with、run
转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details//94402604 本文出自[赵彦军的博客] 文章目录 let 示例1:基础用法 示 ...
- Kotlin实战指南七:单例模式
转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/87941461 本文出自[赵彦军的博客] 单例模式 无参单例模式-线程安全 懒加载 ...
- Kotlin实战指南五:继承、接口
转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/87874895 本文出自[赵彦军的博客] 继承.接口 继承 子类有主构造函数 子类 ...
- Kotlin实战指南十六:Synchronized、Volatile
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/116267707 本文出自[赵彦军的博客] 文章目录 如何创建线程 Thread 如 ...
- Kotlin实战指南十四:协程启动模式
转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/96008400 本文出自[赵彦军的博客] 文章目录 协程启动 DEFAULT LA ...
最新文章
- Roundgod and Milk Tea 贪心
- 例6.12(Java)
- Datatables中文API——回调函数
- 算法导论读书笔记 第4章 分治策略
- 应用程序的8个关键性能指标以及测量方法
- grails框架_Play和Grails Java框架的优缺点
- Linu系统编程---10(Linux的终端,线路规程,网络终端,进程组)
- 20154319 《网络对抗技术》后门原理与实践
- 【Java】获取并打印当前堆栈的方法
- java机器PDF_机器人制作入门(第3版)PDF 下载
- oracle dba create view 失败 解决办法
- poj 2182 给你每个数前面有几个数比他小让你输出次数的编号
- c语言图书管理系统出现的问题,C语言图书管理系统中的问题
- 当前应用拦截NFC响应,不弹出选择框教程
- div和span的标签属性及说明
- 云计算:细分之七大类商业模式
- 【图论】图的定义和术语
- Mybatis-Plus代码生成器CodeGenerator
- spring启动之xml
- 薪酬福利管理太复杂?有实在RPA就够了
热门文章
- f12 卡 谷歌浏览器_干货分享。关于谷歌浏览器的使用技巧,不需要插件
- c mysql批量添加数据类型_mybatis学习之路----mysql批量新增数据
- php隐藏表单提交表单提交表单_表单提交及php处理表单数据的实例
- c语言中的typedef struct相当于java的一个类?,C ++中'struct'和'typedef struct'之间的区别?...
- 4个Keynote、12篇论文分享、40个Poster,CVPR 2021论文分享会全日程公布
- Transformer升级之路:Sinusoidal位置编码追根溯源
- Word Embedding List|ACL 2020 词嵌入长文汇总及分类
- T-GANs:基于“图灵测试”的生成对抗模型
- 活动 | INTERFACE#4 解读搜狗机器翻译技术,体验搜狗旅行翻译宝产品
- 揭秘阿里小蜜:基于检索模型和生成模型相结合的聊天引擎 | PaperDaily #25