Kotlin中可空装箱Int类型行为差异的原因问询
Kotlin可空变量装箱行为差异解释
核心差异:装箱触发时机不同
两个示例的本质区别是装箱操作发生的阶段和次数不一样,===是引用相等比较,只有指向同一个堆对象才会返回true,我们分别拆解两段代码的执行逻辑:
第一段代码(a、b为非空Int类型)的执行逻辑
代码如下:
val a: Int = 100 val boxedA: Int? = a val anotherBoxedA: Int? = a val b: Int = 10000 val boxedB: Int? = b val anotherBoxedB: Int? = b println(boxedA === anotherBoxedA) // true println(boxedB === anotherBoxedB) // false
- Kotlin中非空基础类型(如Int) 会默认映射为JVM的原始类型(对应int),不存在装箱,存储在栈上,没有堆对象引用。
- 每次把原始类型的Int赋值给可空类型
Int?时,都会触发一次装箱操作,调用JDK的Integer.valueOf()方法生成堆上的Integer对象。Integer.valueOf()对-128~127范围的数值做了缓存,相同值会返回同一个缓存对象,所以两次装箱100得到的是同一个对象,引用比较为true。- 10000超出缓存范围,每次调用
Integer.valueOf()都会生成新的Integer对象,两次装箱得到的是不同对象,引用比较为false。
第二段代码(a、b为可空Int?类型)的执行逻辑
代码如下:
val a: Int? = 100 val boxedA: Int? = a val anotherBoxedA: Int? = a val b: Int? = 10000 val boxedB: Int? = b val anotherBoxedB: Int? = b println(boxedA === anotherBoxedA) // true println(boxedB === anotherBoxedB) // true
- Kotlin中可空基础类型(如Int?) 无法映射为JVM原始类型,只要声明就会自动装箱为堆上的Integer对象。
- 声明
val a: Int? = 100的时候,已经完成了唯一一次装箱,生成了一个Integer对象,a持有的是这个对象的引用。 - 后续把a赋值给
boxedA和anotherBoxedA,只是把同一个对象的引用复制了两次,没有触发新的装箱操作,全程只有一个Integer对象。
- 声明
- 不管数值是不是在
-128~127的缓存范围,两个引用都指向同一个对象,所以===比较结果都是true。
内容的提问来源于stack exchange,提问作者Vu Pham
相关产品推荐
相关产品推荐

