Java——详解Integer128陷阱
今天我们来一起探讨一下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方法来比较,因为这个方法比较的两个变量存在堆中的值是否相等
————————————————————————————————————————————————————