马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
lateinit 和 lazy 详解
核心区别
特性lateinitlazy类型可变属性修饰符 var不可变属性委托 val初始化时机手动显式初始化,随时可变首次访问时自动初始化,之后不可变空安全非空类型,但初始值可缺失非空类型,包管有值适用类型不能用于基本类型(Int, Boolean等)可用于任何类型线程安全不包管线程安全默认线程安全SYNCHRONIZED模式检查机制利用前需确保已初始化,否则抛非常自动处理初始化,不会抛出未初始化非常 lateinit 核心用法
- // 声明
- class User {
- lateinit var name: String
-
- fun initialize() {
- name = "John" // 手动初始化
- }
-
- fun greet() {
- if (::name.isInitialized) { // 检查是否已初始化
- println("Hello, $name")
- }
- }
- }
复制代码 最佳利用场景:
- 依赖注入
- Activity/Fragment中的视图绑定
- 单元测试的setUp方法中
- 需要推迟初始化但之后可能需要修改的属性
lazy 核心用法
- // 基本用法
- class User {
- val name: String by lazy {
- println("Computing name...")
- "John" // 计算并返回初始值
- }
- }
- // 指定线程安全模式
- val expensiveData: List<Data> by lazy(LazyThreadSafetyMode.PUBLICATION) {
- loadDataFromDatabase()
- }
复制代码 线程安全模式:
- SYNCHRONIZED:默认模式,线程安全,只执行一次初始化
- PUBLICATION:多线程可能执行多次,但只有第一个效果被利用
- NONE:不包管线程安全,适用于单线程情况,性能最好
最佳利用场景:
- 盘算开销大的属性
- 需要根据条件盘算的只读属性
- 单例模式实现
- 配置项和缓存数据
核心实现原理
lateinit
- 在字节码级别,不为属性分配默认值
- 访问前不举行空检查
- 利用前若未初始化,抛出UninitializedPropertyAccessException
lazy
- 内部利用SynchronizedLazyImpl等实现类
- 持有一个初始化器函数和一个存储效果的AtomicReference
- 首次访问时执行初始化器并缓存效果
如何选择
- 假如属性需要在初始化后修改,利用lateinit var
- 假如属性是只读的且可以延迟盘算,利用lazy val
- 假如处理基本类型,只能利用lazy
- 假如在多线程情况中,优先考虑lazy
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |