User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Kotlin   ›   Kotlin Notes   ›   正文
Kotlin Notes

Kotlin-1.5—内联值类

2021-05-08 17:19:00
1071  0 0
参考目录 隐藏
1) 内联值类
2) 内联值类拓展
3) 序列化
4) 注意事项

阅读完需:约 4 分钟

早在 kotlin 1.3 就已经有了 inline class 的alpha版本。到 1.4.30 进入 beta,如今在 1.5.0 中 终于迎来了 Stable 版本。早期的实验版本的 inline 关键字 在 1.5 中被废弃,转而变为 value关键字

//before 1.5
inline class Password(private val s: String)

//after 1.5 (For JVM backends)
@JvmInline
value class Password(private val s: String)

内联值类与之前内联函数是不同的,而1.5的改版正是为了区分内联函数与内联值类

  • 容易跟内联函数混淆
  • 让人误会编译器的置换机制

Kotlin-函数进阶—内联函数(十六)


内联值类

inline class 主要就是用途就是更好地 “包装” value

有时为了语义更有辨识度,我们会使用自定义class包装一些基本型的value,这虽然提高了代码可读性,但额外的包装会带来潜在的性能损失,基本型的value由于被在包装在其他class中,无法享受到jvm的优化(由堆上分配变为栈上分配)。而 inline class 在最终生成的字节码中被替换成其 “包装”的 value, 进而提高运行时的性能。

早期:

// 函数
fun greetAfterTimeout(duration:Durations){
    println(duration)
}

// class 类---实体类
class Durations(val millis: Long)

// 协助我们产生正确的时间长度
fun seconds(value:Int):Durations= Durations(value*1000L)

fun main() {
    greetAfterTimeout(seconds(2)) // 类型不安全,不知道是 分,秒,毫秒 所以加入seconds函数来进行转换
}

内联值类:

fun greetAfterTimeout(duration:Durations){
    println(duration)
}

// 底层 当一个函数传入内联值类时,编译器会把类换成基本类型
//fun greetAfterTimeout-R44Lxco(duration:Duration) ->> fun greetAfterTimeout-R44Lxco(duration:Long)


//class Duration(val millis: Long)

// 内联值类
@JvmInline
value class Durations(val millis: Long)

// 协助我们产生正确的时间长度
fun seconds(value:Int):Durations= Durations(value*1000L)

@OptIn(ExperimentalTime::class)
fun main() {
    greetAfterTimeout(seconds(2)) // 类型不安全,不知道是 分,秒,毫秒 所以加入seconds函数
    // 我们用 seconds 回传 Duration ,编译器也会把这个内联值类换掉
    // greetAfterTimeout-R44Lxco(2*1000L)

}

底层——当一个函数传入内联值类时,编译器会把类换成基本类型

Duration 实例在字节码中被替换为 Long 类型

当我们查看两段程序的结果就能清楚的知道区别了:

早期的程序打印结果:

com.enmalvi.jvmiline.Durations@681a9515

内联值类打印结果:

Durations(millis=2000)

在我们使用 println(duration) 来打印输出,并没有用 println(duration.millis) 输出的时候,使用内联类的程序可以清楚的打印出结果,而另一个只能打印出地址。

使用内联值类的优势:

  • 类型安全
  • 基本类型
  • 性能
  • 可显式的表面特定类型
  • 没有为了分配对象而损失性能

内联值类拓展

内联值类可以定义成员函数及属性,像这个例子它应该在每次访问的时候被计算出来

@JvmInline
value class Name(private val s:String){
    val length:Int
        get() = s.length
}

指定初始化化块

@JvmInline
value class Name2(val s:String){
    init {
        require(s.isNotEmpty())
    }
}

构造参数中有且只能有一个成员变量,变量必须为 val


序列化

内联值类还可以序列化,但是与普通类的序列化结果会有所不同

普通类序列化

@Serialization
class Color(val rgb:Int){

}

@Serialization
data class NamedColor(val color: Color,val  name: String)

fun main() {
    println(JSONObject.toJSON(NamedColor(Color(0),"black")))
}

结果

{"color":{"rgb":0},"name":"black"}

内联值类

@Serialization
@JvmInline
value class Color(val rgb:Int){

}

@Serialization
data class NamedColor(val color: Color,val  name: String)

fun main() {
    println(JSONObject.toJSON(NamedColor(Color(0),"black")))
}

结果

{"name":"black","color-EsE2G5M":0}

从结果可以看出内联值类的序列化将直接输出值,并没有层次的包含。


注意事项

底层加上后缀是为了区分,不区分会在class字节码里造成一样的签名

@JvmInline
value class Names (val value:String)

@JvmInline
value class Password(val value: String)

fun record(name: Names){}
fun record(password: Password){}

//底层
//fun record-7dj_djg(name:String)
//fun record-Gwat88I(password:String)
  • 防止重载函数的参数经过 inline 后出现相同签名的情况
  • 防止从Java侧调用到参数经过 inline 后的方法

如果java想要调用有内联值类的方法需要加上@JvmName() 来指定名称,因为内联值类有后缀签名

// 从java调用 需要添加 @JvmName()
@JvmName("greetAfterTimeouts")  // 其中 Durations 是内联值类
fun greetAfterTimeouts(duration:Durations){
    println(duration)
}

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 294点赞 593500浏览

随机文章
Redis笔记—Hash散列与Zset有序集合
5年前
HttpMessageConverter—关于一个字符串到java对象的转化
5年前
SpringSecurity—OAuth 2(九)第三方应用优化
5年前
Java—反射机制
5年前
SpringSecurity—实现自动登录功能
5年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1927 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 593500 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付