容易被忽视的几个 Kotlin 细节, value class 执行效率竟然这么高
- 如果评论区没有及时回复,欢迎来公众号:ByteCode 咨询
- 公众号:ByteCode。致力于分享最新技术原创文章,涉及 Kotlin、Jetpack、算法、译文、系统源码相关的文章
在之前的文章中,分析过 Kotlin 1.5 宣布了一个重磅特性 value class 这是一个非常实用的特性,提高代码的可读性同时,还可以提高性能,因为编译器会对它进行更深层次的优化。主要包含了以下内容,没有看过的小伙伴可以前去查看 。
inline class和value class有什么区别value class不能被继承,但是可以实现接口- 当传递的对象为空时,
value class将会失去内联效果 value class禁止使用===可以使用==
而今天这篇文章主要介绍 value class 和 data class 的区别,这可能是平时在做业务开发的时候,容易被忽视的几个细节。通过这篇文章,你将学习到以下内容。
- 什么是
value class? - 什么是
data class? value class和data class的区别value class占用更少的内存,执行效率更高value class执行效率比data class快多少value class没有copy()方法value class构造函数只能传入一个参数value class为什么不能重写equals()、hashcode()方法value class和data class都不能被继承
什么是 value class
value class 表示内联类,需要在主构造函数中传入一个参数,而且需要用 val 进行修饰, 编译成 Java 代码之后,会替换为传进去的值,代码如下所示。
|
正如你所见,编译后的 Java 代码并没有创建额外的对象,而是将在 Kotlin 中创建的对象 User 替换为传进去的值 DHL。
什么是 data class
data class 表示数据类,编译器会根据主构造函数声明的参数,自动生成 quals() 、 hashCode() 、 toString() 、 componentN() 、 copy() 、 setXXX() 、 getXXX() 等等模板方法,将我们从重复的劳动力解放出来了,专注于核心业务的实现。
data class User(val name: String) |
value class 和 data class 的区别
Value Class 占用更少的内存,执行效率更高
为了保证相同的逻辑应用在各个地方,通常我们对于 model 中参数的验证都会封装在当前 model 中,比如在一个 data class User 中检查用户名是否为空。
data class User(var name: String? = null) { |
当我们每次创建 User 对象的时候,都会在堆中分配对象,需要占用更多的内存,同时也会使我们的代码执行效率更低。因为对象创建过程是非常的慢。会经历两个过程:类加载过程、对象创建过程。
类加载过程
- 会先判断这个类是否已经初始化,如果没有初始化,会执行类的加载过程
- 类的加载过程:加载、验证、准备、解析、初始化等等阶段,之后会执行
<clinit>()方法,初始化静态变量,执行静态代码块等等
对象创建过程
- 如果类已经初始化了,直接执行对象的创建过程
- 对象的创建过程:在堆内存中开辟一块空间,给开辟空间分配一个地址,之后执行初始化,会执行
<init>()方法,初始化普通变量,调用普通代码块
value calss 的出现很好的帮助我们解决了这些问题,它使代码执行效率更高,占用更少的内存。这全都得益于 Kotlin 编译器对它进行大量的优化。
|
正如你所见当我们在实例化 User 的时候,并没有在堆中分配对象,而是将传递给方法 login() 的参数 User 替换为传进去的值 DHL。
Value class 执行时间比 data class 快多少
接下来我们用一个例子来感受一下 value class 比 data class 快多少,代码如下所示。
data class User1(val name: String) |
上述代码唯一的区别 User1 用 data class 来声明的,User2 用 value class 来声明的,最后的执行时间如下所示。
measure data class time 6.790241 ms |
value class 执行效率远远高于 data class。当数据量很大时,它们的差距也会越来越大。
Value class 没有 copy () 方法
value calss 同 data class 一样可以有 init function,也可以有 internal function,方便我们封装业务逻辑。
但是 value calss 不会生成 copy() 方法,而 data class 编译后会生成 copy() 方法,如下所示。
data class User(val name: String, val pwd: String) |
这也意味着通过 data calss 创建对象实例副本,我们不需要重写所有的参数,可以指定需要改变的参数。
user = user.copy(name = "hi-dhl") |
而 value calss 只能通过构造函数去创建对象,需要显示指定所有的参数。
Value class 构造函数只能传入一个参数
现阶段 value class 只能在构造函数中传入一个参数,而且需要用 val 进行修饰,而 data calss 支持在构造函数中添加多个参数,参数可以用 val 或者 var 声明。不过在不久的将来 Kotlin 将会支持在 value class 构造函数中添加多个参数,如下图所示。

Value class 和 data class 都不能被继承
因为 value class 和 data class 编译后将会添加 fianl 修饰符,因此不能被继承,同样也不能继承其他的类,如下图所示。



Value class 不能重写 equals () 、hashcode () 方法
value class 相比于 data class 不能重写 equals() 和 hashcode() 方法, 如下图所示。

equals() 方法用于比较两个参数的内容是否相同,关于 Kotlin 中的 == 和 === 以及 eauals 方法的区别,可以查看我另外一篇文章 解密 Koltin 中的 == 和 === 以及 eauals。
因为 value class 构造函数只能传入一个参数,而且必须用 val 进行修饰,所以不存在需要比较两个相同的参数场景,因此 Kotlin 不让重写 equals() 和 hashcode() 方法。
如果有帮助点个赞就是对我最大的鼓励
代码不止,文章不停
欢迎关注公众号:ByteCode,持续分享最新的技术
最后推荐长期更新和维护的项目:
个人博客,将所有文章进行分类,欢迎前去查看 https://hi-dhl.com
KtKit 小巧而实用,用 Kotlin 语言编写的工具库,欢迎前去查看 KtKit
计划建立一个最全、最新的 AndroidX Jetpack 相关组件的实战项目以及相关组件原理分析文章,正在逐渐增加 Jetpack 新成员,仓库持续更新,欢迎前去查看 AndroidX-Jetpack-Practice
LeetCode / 剑指 offer / 国内外大厂面试题 / 多线程题解,语言 Java 和 kotlin,包含多种解法、解题思路、时间复杂度、空间复杂度分析

近期必读热门文章
- 本文作者:hi-dhl
- 本文标题:容易被忽视的几个 Kotlin 细节, value class 执行效率竟然这么高
- 本文链接:https://hi-dhl.com/2022/02/28/kotlin/17-ValueClass-DataClass/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 hi-dhl

