128陷阱:
integer a = 127 , Integer b = 127 时 , a 和 b 被自动装箱到同一个对象中 , 所以 用 == 号判断时, 认为是相等的. 而当等于
128 时,则是分装在两个对象中的 , 自然地址也不会相等 , 所以 == 号 判断结果为 false . 超过128 结果也是一样的 .
所以在比较两个包装类的对象时, 尽量使用 equals 方法 ,这样可以得到你想要的结果 , 使用 == 号容易导致 128陷阱 .
简单来讲就是:在小于127大于-128的时候,自动装箱的是同一个地址存在的数值。大于127时,自动装箱的不是同一个对象,所以地址不同。
这就是所谓的 “128陷阱” .
解释:
在Java中,Interger是数据类型int的封装类,Java设计者是这么认为的:
每次都要开辟新空间会占用大量的资源,因此他们规定在-128~127(因为Java设计者认为大家对数的使用大多在100以内)之间的Integer类型的变量,直接指向常量池中的缓存地址,不会new开辟出新的空间。
首先是我们先简单说一下自动装箱和拆箱的一些机制
Integer(int的封装类)使用le缓存策略,缓存的这些对象都是经常使用到的(-128至127之间的数字),防止每次自动装箱都创建一次对象的实例。
public class Test {
public static void main(String[] args) {
Integer a = 56;
int a2 = 56;
Integer b = 56;
Integer c = new Integer(56);
System.out.println(a1 == a2);
System.out.println(a1==b);
System.out.println(a1==c);
Integer d = 128;
Integer e = 128;
System.out.println(d == e);
System.out.println(d.intValue()==e.intValue());
System.out.println(d.equals(e));
}
}
输出结果:
分析运行结果:
1.true 证明此时a1(integer)和a2(int)都指向了常量池中的56。
2 true 证明了两个integer也是同时指向了常量池中的56(缓存机制)。
3 false 证明了此时new方法出来的integer对象在堆中,故引用地址不同是false。
4 false 证明了只有-128~127(128陷阱)会加载到常量池中,而其他会在堆中开辟不同的空间。
5 true 证明了也可以主动调用拆箱方法使得integer的值得以比较。
6 true 证明了integer重写了equal()方法,更方便我们应用。
如果想要正确比较的话,一定要拆箱比较,即在变量后加intValue()方法,也可以调用equal()
Integer i = 56; 自动装箱,相当于调用了Integer.valueOf(56)方法。进行装箱的时候首先判断i值是否在-128和127之间,如果在-128和127之间则直接从IntegerCache.cache缓存中获取指定数字的包装类;不存在则new出一个新的包装类。
使用i的时候,自动拆箱,相当于调用了Integer.intValue()的方法。
(源码中)IntegerCache内部实现了一个Integer的静态常量数组,在类加载的时候,执行static静态块进行初始化-128到127之间的Integer对象,存放到cache数组中。cache属于常量,存放在java的方法区中。