自动装箱和拆箱的几个细节
Posted wengzp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动装箱和拆箱的几个细节相关的知识,希望对你有一定的参考价值。
装箱和拆箱
装箱和拆箱也比较简单,我就不解释了,直接看代码就行了。
Integer box = 2; // 自动装箱
System.out.println(box); // 自动拆箱
虽然装箱拆箱简单易理解,但是其实 JDK 源码中有一些小细节,如果平时没注意,可能一不小心就踩了个坑。
细节一
public class Boxing {
public static void main(String[] args) {
System.out.println("Integer.valueOf(-128) == Integer.valueOf(-128) ? " + (Integer.valueOf(-128) == Integer.valueOf(-128)));
System.out.println("Integer.valueOf(-129) == Integer.valueOf(-129) ? " + (Integer.valueOf(-129) == Integer.valueOf(-129)));
System.out.println("Integer.valueOf(128) == Integer.valueOf(128) ? " + (Integer.valueOf(128) == Integer.valueOf(128)));
System.out.println("Integer.valueOf(127) == Integer.valueOf(127) ? " + (Integer.valueOf(127) == Integer.valueOf(127)));
}
}
输出:
Integer.valueOf(-128) == Integer.valueOf(-128) ? true
Integer.valueOf(-129) == Integer.valueOf(-129) ? false
Integer.valueOf(128) == Integer.valueOf(128) ? false
Integer.valueOf(127) == Integer.valueOf(127) ? true
这个输出就比较奇怪了,让我们直接看一下源码,看看 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);
}
这下就清楚明白了,原来是 Integer 做了一个数组,缓存了 -128 到 127 之间的 Integer,在这个范围内的 Integer,会直接返回数组中对应索引的 Integer,而超出这个范围的,则是直接 new Integer(i)。
其实这么做也是挺合理的,-128到127是比较常用的范围,直接缓存起来,也不用每次都去生成实例,减少了开销。
细节二
public class Boxing {
public static void main(String[] args) {
Integer box1 = 2;
Integer box2 = box1;
System.out.println(box2 == box1);
box1++;
System.out.println(box2 == box1);
}
}
输出:
true
false
为什么我们对 box1 做了个自增之后,就引用不一致了呢?
这里是因为 box1++ 实际上进行了拆箱又装箱。
// box1++
int box1 = box1.intValue();
box1++;
Integer box1 = new Integer(box1);
经过这个拆箱又装箱,引用肯定就跟原来的不一样了。
细节三
System.out.println("new Integer(2) == new Integer(2) ? " + (new Integer(2) == new Integer(2)));
System.out.println("new Integer(2).equals(new Integer(2)) ? " + new Integer(2).equals(new Integer(2)));
输出:
new Integer(2) == new Integer(2) ? false
new Integer(2).equals(new Integer(2)) ? true
== 为 false,而 equals 为 true,这个我们很自然应该会想到, equals 是不是被重写了呢?让我们直接看源码。
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
这下就很直观了,JDK 对传进来的参数 obj 做了一个拆箱,直接判断值,而不是引用,所以应该返回 true。
写在最后
虽然拆箱装箱是一个很简单的过程,但是这几个细节,平时遇到了,如果我们不去看源码,可能有时候会一头雾水,一看源码,就豁然开朗。所以其实日常开发中,也应该有一个踩到坑就看看源码怎么实现的习惯的。
以上是关于自动装箱和拆箱的几个细节的主要内容,如果未能解决你的问题,请参考以下文章