【译】kotlin中lateinit和by lazy的区别

原文内容来自 Kotlin - Property initialization using “by lazy” vs. “lateinit”

lazy { ... } delegate can only be used for val properties, whereas lateinit can only be applied to vars, because it can't be compiled to a final field, thus no immutability can be guaranteed;

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

lateinit var has a backing field which stores the value, and by lazy { ... } creates a delegate object in which the value is stored once calculated, stores the reference to the delegate instance in the class object and generates the getter for the property that works with the delegate instance. So if you need the backing field present in the class, use lateinit

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

In addition to vals, lateinit cannot be used for nullable properties and Java primitive types (this is because of null used for uninitialized value)

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

lateinit var can be initialized from anywhere the object is seen from, e.g. from inside a framework code, and multiple initialization scenarios are possible for different objects of a single class. by lazy { ... }, in turn, defines the only initializer for the property, which can be altered only by overriding the property in a subclass. If you want your property to be initialized from outside in a way probably unknown beforehand, use lateinit

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

Initialization by lazy { ... } is thread-safe by default and guarantees that the initializer is invoked at most once (but this can be altered by using another lazy overload). In case of lateinit var, it's up to the user's code to initialize the property correctly in multi-threaded environments.

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

A Lazy instance can be saved, passed around and even used for multiple properties. On contrary, lateinit vars do not store any additional runtime state (only null in the field for uninitialized value).

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

If you hold a reference to an instance of Lazy, isInitialized() allows you to check whether it has already been initialized (and you can obtain such instance with reflection from a delegated property). To check whether a lateinit property has been initialized, you can use property::isInitialized since Kotlin 1.2.

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

A lambda passed to by lazy { ... } may capture references from the context where it is used into its closure.. It will then store the references and release them only once the property has been initialized. This may lead to object hierarchies, such as Android activities, not being released for too long (or ever, if the property remains accessible and is never accessed), so you should be careful about what you use inside the initializer lambda.

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

相关推荐

从大一开始就开始学习Java,一路走来真的不算容易,每次面试都被压力,不过这次终于达成了自己的一大心愿!时间线和面经:8.17-投递9.1-一面实习+项目拷打看门狗机制讲一下redis加锁解锁的本身操作是什么Lua脚本是干什么的udp和tcp讲一下流量控制讲一下令牌桶算法说一下大端和小端是什么线程和协程有什么区别怎么切换协程切换的时候具体做了什么对于程序来说,你刚才提到的保存和恢复现场,这个现场有哪些信息udp优势现在有一个客户端和服务端,要实现TCP的通信,我们的代码要怎么写服务器怎么感知有新的连接怎么处理多个客户端的请求连接TCP怎么处理粘包和分包现在有两个文件,然后每个文件都有一亿条URL,每个的长度都很长,要怎么快速查找这两个文件共有的URLHashmap底层说一下怎么尽量提升插入和查询的效率如果要查找快,查询快,还有解决非空的问题,怎么做LoadingCache了解吗手撕:堆排序9.4-二面部门的leader,超级压力面拷打实习+项目,被喷完全没东西类的加载到垃圾回收整个底层原理讲一遍类加载谁来执行类加载器是什么东西,和进程的关系Java虚拟机是什么东西,和进程的关系如果我们要执行hello world,那虚拟机干了什么呢谁把字节码翻译成机器码,操作时机是什么Java虚拟机是一个执行单元吗Java虚拟机和操作系统的关系到底什么,假如我是个完全不懂技术的人,举例说明让我明白一个操作系统有两个Java程序的话,有几个虚拟机有没有单独的JVM进程存在启动一个hello world编译的时候,有几个进程JVM什么时候启动比如执行一条Java命令的时候对应一个进程,然后这个JVM虚拟机到底是不是在这个进程里面,还是说要先启动一个JVM虚拟机的进程垃圾回收机制的时机能手动触发垃圾回收吗垃圾回收会抢占业务代码的CPU吗垃圾回收算法简单说说垃圾回收机制的stop the world存在于哪些时机垃圾回收中的计算Region的时候怎么和业务代码并行执行假如只有一个线程,怎么实现并行Java为什么要这么实现Java效率比C++慢很多,那为什么还要这样实现Java虚拟机到底是什么形式存在的说一下Java和C++的区别还有你对Java设计理念的理解无手撕面试结束的时候,我真的汗流浃背了,面试官还和我道歉,说他是故意压力面想看看我的反应的,还对我给予了高度评价:我当面试官这么多年,你是我见过最好的一个9.9-三面临时通知的加面,就问了三十分钟项目9.11-hr面问过往经历,未来计划,想从腾讯实习中得到什么?当场告知leader十分满意我,所以直接ochr面完一分钟官网流程变成录用评估中,30分钟后mt加微信告知offer正在审批9.15-offer这一次腾讯面试体验真的不错,每个面试官能感觉到专业能力很强,反馈很足,比起隔壁某节真是好太多以后就是鹅孝子了
三本咋了:当面试官这么多年你是我见过的最好的一个
你面试被问到过哪些不会的...
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务