“128 陷阱”通常指的是在 Java 中,对于Integer
类型(包装类)在一定范围内使用==
判断时,可能会出现与预期不一致的结果。
要了解128陷阱我们就不得不知道装箱和拆箱这两个概念 因为128陷阱是由自动拆装箱产生的问题
装箱:将基本数据类型转换为包装器类型(Integer
、Double
、Boolean
等) 使用valueOf()方法进行
int num = 42;
Integer integerObj = Integer.valueOf(num);
拆箱:将包装器类型转换为基本数据类型 通过调用包装类的xxxValue()
方法来完成拆箱,其中xxx
代表对应的基本数据类型。
例如,对于Integer
类,可以使用intValue()
方法进行拆箱,将Integer
对象转换为int
类型
Integer integerValue = 42;
int intValue = integerValue.intValue(); // 通过 intValue()方法拆箱
回过头来,在 Java 中,当使用自动装箱(将基本数据类型自动转换为对应的包装器类型)将int
值赋给Integer
对象时,如果值在-128
到127
之间,Java 会使用一个内部的缓存机制来复用已经创建好的Integer
对象,而不是每次都创建新的对象。也就是说,在这个范围内的Integer
变量可能会指向同一个缓存对象,使用==
比较时会返回true
。
然而,对于不在-128
到127
这个范围内的值,自动装箱时会创建新的Integer
对象,此时使用==
比较两个Integer
对象的引用时,结果为false
,因为它们指向不同的对象。
究其根本是Integer.valueOf的逻辑代码导致的
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)//Integer 类有一个内部静态类 IntegerCache,它用于缓存-128到127之间的整数对象 在此行我们可以知道 在-128到127之间的值 会放在cache静态数组中
return IntegerCache.cache[i + (-IntegerCache.low)];//cache是 IntegerCache 类中的一个静态数组,用于存储这些缓存的整数对象。
return new Integer(i);//不在-128到127之间的值则会开辟一个新的内存空间进行存放
}
知道了底层原理 我们可以看一个例子
public static void main(String[] args) {
Integer a = 101;
Integer b = 101;
System.out.println(a == b);
Integer c = 1001;
Integer d = 1001;
System.out.println(c == d);
}
结果显而易见
true
false
部分同学此处可能仍有疑问为什么在“c==d”例子中 不同的空间 使用“==”就会判断错误
这里就涉及到“==”的知识点了
"== "在基本数据类型:是依据值内容判断,在引用类型时:则是根据地址判断
除了Integer
类型外,Byte
、Short
、Character
和Long
这几个类的valueOf
方法的实现也有类似的缓存机制,但具体的范围可能有所不同。对于Double
和Float
类型,则没有这样的缓存机制。