Integer变量的比较bug
Integer变量的比较bug
执行下例代码,会出现神奇现象:i_0 等于 i_1,但 i_2 不等于 i_3。明明都是一样的数值,前者为何相等,后者为何不等呢?
public class Main {
public static void main(String[] args) {
Integer i_0 = 100;
Integer i_1 = 100;
System.out.println(i_0 == i_1);
Integer i_2 = 128;
Integer i_3 = 128;
System.out.println(i_2 == i_3);
}
}
我们只知道Integer
是int
型的装箱类型,但并不知Integer
的庐山真面目。
Integer
中有一个静态私有类IntegerCache
,IntegerCache
有一个属性cache[],这个属性被用来存储 -128~127 范围内的整数,不过这个范围的上限支持修改,设置JVM运行参数-Djava.lang.Integer.IntegerCache.high=
。
Integer.class
源码
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;
// 获取 java.lang.Integer.IntegerCache.high参数值(定义参数-Djava.lang.Integer.IntegerCache.high=2000,这样你的i_2==i_3就可以实现了)
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
/*
* 没有设置过-Djava.lang.Integer.IntegerCache.high参数则为null——不进入if
* 这一步的目的是将获取到cache[]的右极限
* */
if (integerCacheHighPropValue != null) {
try {
// string型转int型
int i = parseInt(integerCacheHighPropValue);
// 比较 设置值 和 127,取值大者
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
/**
* 比较 刚比较出来的最大值 和 0x7fffffff+128-1 比较,取最小者
* 为什么做这一步呢,不是多此一举吗?其实是为了预防传入值过大,超
* 出Integer所能表示的数值的最高限制
*/
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;// 为high赋值,默认赋值127
// 重新定义cache的大小,127-(-128)+1 = 256【这是没有设置过-Djava.lang.Integer.IntegerCache.high参数的前提下】
cache = new Integer[(high - low) + 1];
int j = low;//low = -128
// 依次向cache中填入数据(从-128开始)
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
// 断言high是大于等于127的,不过这段代码我是没有理解其用意
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
由上述的代码可以看出,Integer
的cache[]的底线一直是-128
,而其最大值是可以通过-Djava.lang.Integer.IntegerCache.high
进行修改,修改了最大值,相对应的cache的大小也会发生变化。
了解了Integer
的cache[]
,下面开始解释为何 i_2 不等于 i_3?
public static Integer valueOf(int i) {
/**
* 判断i是否处于low和high之间,如果处于他们之间,则不会new一个Integer新对象,
* 而是把cache[]中的对象返回;只有超出[low,high]范围的数值才new一个新对象
* 并返回。所以如果我们设置给JVM的参数java.lang.Integer.IntegerCache.high
* 的值满足i_2 == i_3的范围,那么就可以让结果为true
* */
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
cache[] 完整代码是:
static final Integer cache[];
这说明cache[]是保存在方法区的常量,一旦加载便不再被修改,仅能访问。
所以建议在比较装箱数据时使用
.equals(obj)
方法
如:i_2.equals(i_3)
本文来自博客园,作者:勤匠,转载请注明原文链接:https://www.cnblogs.com/JarryShu/articles/18163705