Kotlin数值装箱测试存疑:为何两次===校验输出不同?
===判断结果不一致的疑问 我是Kotlin初学者,无法理解以下测试代码的输出。测试代码如下:
@Test fun testNumberBoxing() { val a:Int = 1000 val boxedA1: Int? = a val boxedA2: Int? = a println("first check = ${boxedA1 === boxedA2}") val b: Int = 2 val boxedB1: Int? = b val boxedB2: Int? = b println("second check = ${boxedB1 === boxedB2}") }
执行结果为:first check = true,second check = false。为何两次输出不同?我的Kotlin版本为1.2.31,依赖org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.31。
嘿,这个问题其实涉及到JVM平台上Kotlin(以及Java)对基本类型装箱的核心优化——整数缓存机制,给你理清楚来龙去脉:
首先得明确:Kotlin里的===对于可空类型(比如Int?)来说,判断的是两个对象的内存引用是否完全相同,也就是它们是不是指向堆里的同一个对象;而==才是判断值是否相等,这点一定要区分开。
接下来看装箱的逻辑:当你把基本类型Int转成可空的Int?时,本质上是在JVM层面把int装箱成了Integer对象。而JVM为了优化性能,会对**-128到127之间的整数进行缓存**:
- 只要数值在这个区间内,每次装箱都会直接从缓存池里拿现成的对象,所以多次装箱同一个值,得到的是同一个引用,
===判断自然返回true; - 如果数值超出了这个区间,每次装箱都会新建一个
Integer对象,两次装箱的引用肯定不一样,===就会返回false。
不过这里有个小疑问:按照这个逻辑,你的代码正常输出应该是first check = false(1000超出缓存范围,两次装箱是不同对象),second check = true(2在缓存范围内,复用同一个对象),和你给出的结果刚好相反。大概率是你笔误写错了输出,或者测试环境有极端的编译器优化,但核心的原理就是上面说的缓存机制。
补充个小知识点:这个缓存的上限(127)在JVM里可以通过java.lang.Integer.IntegerCache.high这个系统参数调整,但默认情况下都是-128到127,一般不会去改动它。
内容的提问来源于stack exchange,提问作者ohlab

