在看Kotlin的基本类型时,文档提到,Kotlin中所有东西都是对象;并且数字在 Java 平台是物理存储为 JVM 的原生类型,除非我们需要一个可空的引用(如 Int?)或泛型。 后者情况下会把数字装箱。
刚看到数字装箱,猜测是不是类似Java中基本类型的包装类,int —> Integer... 然后例子中又提到一个数字装箱不一定保留同一性,判断的是两个数值的引用地址。如果是按照 Integer来装箱,boxedA 和 anotherBoxedA 应该是两个不同的 Integer对象,引用一定不同。
图1. Kotlin装箱不一定保留同一性
实践出真知,上代码
fun testPacking() {
val a: Int = 10000
println(a === a) // 输出“true”
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA === anotherBoxedA) // !!!输出“false”!!!
}
fun testPacking2() {
val a: Int = 100
println(a === a) // 输出“true”
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA === anotherBoxedA) // !!!输出“true”!!!
}
上面的代码中,a的值不同,造成的结果也不同;查看一下Kotlin编译出的Java字节码,选中IDEA上面菜单栏的 Tools —> Kotlin —> Show Kotlin Bytecode,在打开的Kotlin Bytecode窗口中点击 Decompile
图2. 查看Kotlin Bytecode
上面代码编译成字节码后,对应的代码如下
public final void testPacking() {
int a = 10000;
boolean var2 = true;
System.out.println(var2);
Integer boxedA = Integer.valueOf(a);
Integer anotherBoxedA = Integer.valueOf(a);
boolean var4 = boxedA == anotherBoxedA;
System.out.println(var4);
}
public final void testPacking2() {
int a = 100;
boolean var2 = true;
System.out.println(var2);
Integer boxedA = Integer.valueOf(a);
Integer anotherBoxedA = Integer.valueOf(a);
boolean var4 = boxedA == anotherBoxedA;
System.out.println(var4);
}
果不其然,是通过 Integer 将数字进行了装箱操作,但是两个数值得到的值确实不一样的,查看Integer.valueOf()的源码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
发现i的值在-128到127之间时,是从IntegerCache.cache中拿的,而不在该范围则是每次创建一个Integer对象
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
// 省略部分代码......
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
所以Kotlin文档的示例代码中说的不一定保留同一性,表示的是数字范围在[-128, 127],引用相同,其他不同
网友评论