128陷阱是java面试中关于Interger包装类的一个非常经典的底层机制考点
简单来说,它的现象是:当你比较两个数值相等的 Integer 对象时,如果数值在 -128 到 127 之间,结果为 true;如果超过这个范围,结果却是 false。
1. 现象演示
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // 结果是 true
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // 结果是 false —— 这就是所谓的“陷阱”
2. 为什么会这样?(底层原理)
这个现象是由自动装箱和Interger缓存机制共同导致的。
A. 自动装箱
当你写 Integer a = 127; 时,编译器会自动将其转换为: Integer a = Integer.valueOf(127);
B. IntegerCache 缓存池
我们来看一下 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);
}
-
缓存机制: Java 为了优化性能,在类加载时预先创建了一个缓存数组,存储了 -128 到 127 之间的
Integer对象。 -
命中缓存: 如果你赋值在这个范围内,
valueOf直接返回缓存池里已经存在的那个对象。由于a和b指向的是内存中同一个对象,==比较地址当然返回true。 -
超出范围: 如果数值是 128,
valueOf会执行new Integer(128)。这意味着c和d是堆内存中两个独立的对象。两个不同对象的内存地址不同,所以==结果为false。
3. 面试官的连环追问
-
为什么要设置这个缓存? 为了性能。-128 到 127 是编程中最常用的整数范围,重复利用这些对象可以显著减少对象创建次数,降低垃圾回收(GC)的压力。
-
这个范围可以改吗? 可以。可以通过 JVM 参数
-XX:AutoBoxCacheMax=<size>来修改上限,但下限 -128 是固定的。 -
其他类型有类似的陷阱吗?
-
Byte,Short,Long都有同样的 -128~127 缓存。 -
Character有 0~127 的缓存。 -
注意:
Float和Double没有缓存,因为某个范围内的浮点数是无限多的。
-
4. 避坑指南(结论)
在实际工程中,为了避免这个陷阱,比较两个包装类(如 Integer, Long)的值时,永远不要使用 ==,而应该使用 equals() 方法。
Integer c = 128;
Integer d = 128;
System.out.println(c.equals(d)); // 永远返回 true,因为它比较的是数值内容

1348

被折叠的 条评论
为什么被折叠?



