今天我们来一起探讨一下Java的128陷阱
首先我们通过代码对128陷阱进行一个认知
public static void main(String[] args){
Integer a = 127 ;
Integer b = 127 ;
Integer c = 128 ;
Integer d = 128 ;
Integer e = 1000 ;
Integer f = 1000 ;
int a1 = 127;
int b1 = 127;
int c1 = 128;
int d1 = 128;
int e1 = 1000;
int f1 = 1000;
System.out.println(a == b);
System.out.println(c == d);
System.out.println(e == f);
System.out.println(a1 == b1);
System.out.println(c1 == d1);
System.out.println(e1 == f1);
}
运行的结果如下:
可以看到,当数据为基本类型int的时候,运行的结果都是true,而如果是封装类型Integer的时候,数据为127的时候使true,128和1000都为false,那这是为什么呢?
首先我们要理解==比较的是什么,它比较的是栈中数据是否相同,我们都知道,基本类型的数据的变量名和值都存在栈中(作为类的属性的情况除外),因此,所有int类型的数据运行都会为true。
同样,我们也都知道,引用类型会把它的值存在堆中,栈中存储的是变量名及堆中数据的地址,揪下来我们要引入一个概念
基本类型的包装存在自动拆装箱机制
那么什么是自动拆箱与自动装箱呢,简单的来说
Integer a = 1;其实代表的是Integer a = new Integer(1);我们不需要去进行初始化,这个方法会自己初始化在堆中开辟一片区域存储数据。自动拆箱也类似int b = a;代表的是int b = Integer.valueOf(a);同样不需要我们主动调用方法。
说完了自动拆装箱,大家就可以理解为什么会出现false,因为每次初始化都会开辟新的区域,虽然两块区域可能储存的值相同,但是它们是堆中两块不同的区域,栈中存储的地址不同,因此比较会出现false
。
最后一个问题就是,为什么值为127 的时候就会认为是true?
Java设计者认为:
每次都要开辟新空间会占用大量的资源,因此他们规定在-128~127(因为Java设计者认为大家对数的使用大多在100以内)之间的Integer类型的变量,直接指向常量池中的缓存地址,不会new开辟出新的空间。
因此当值在 -128~127区间内的时候,两个相同值的变量会指向相同地址,这就是Java中的128陷阱
除此之外,我们来看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;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
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() {}
}
总结 在基本类型的包装类运用时,还是更推荐大家使用equals方法来比较,因为这个方法比较的两个变量存在堆中的值是否相等
亲测System.out.println(e.equals(f));
为true
原文链接:Java——详解Integer128陷阱
注意:本文归作者所有,未经作者允许,不得转载