深入研究Integer
程序员文章站
2024-03-08 15:58:52
...
Integer 数据类型在项目中随处可见,由于回想起曾经在使用 Inetger 时引发的一个bug,因此对 Integer 做一下深入的解析。
从举一个例子开始
public static void main(String[] args) {
Integer num1 = 1;
Integer num2 = 1;
System.out.println(num1 == num2);
Integer num3 = 200;
Integer num4 = 200;
System.out.println(num3 == num4);
}
最终输出的是:
true
false
num1==num2的输出是true,和预期结果一样。但是这里的num3和num4明明都是200,比较之后得到的却是false。
通过反编译源代码之后,有了发现
public static void main(String[] args){
Integer num1 = Integer.valueOf(1);
Integer num2 = Integer.valueOf(1);
System.out.println(num1 == num2);
Integer num3 = Integer.valueOf(200);
Integer num4 = Integer.valueOf(200);
System.out.println(num3 == num4);
}
原来在代码编译的时候,编译器自动把 Integer num1 = 1 编译成了 Integer num1 = Integer.valueOf(1)。 这个过程就是java包装类型的自动装箱
。
接着看一下 Integer.valueOf() 这个方法,它是Intetger提供的静态工厂方法,源码如下
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
再进去 IntegerCache 这个类看个究竟
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() {}
}
IntegerCache 源码中分别定义了 low、high、cache[]
- low 默认是-128,表示缓存的最小值
- high 默认是127,表示缓存的最大值,high值可以通过JVM参数
-XX:AutoBoxCacheMax
来更改 - cache[] 存放了 low 到 high 之间的所有值
最终看 valueOf() 的逻辑可以得出:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
默认情况下:
- 如果输入的int值在 -128 ~ 127之间,则返回的Integer对象是从 IntegerCache 的 cache 数组中取出来的对象,这也就是为什么num1会等于num2的原因;
- 如果输入的int值不在 -128 ~ 127范围内,则每次返回的都是新的Integer对象,这也就是为什么num3不等于num4的原因;
如果想改变 IntegerCache 中的 high 值,可以通过JVM参数 -XX:AutoBoxCacheMax 来设置
启动时把 -XX:AutoBoxCacheMax 的值设置成10000,IntegerCache 在初始化的时候会读取配置的参数并进行设置,再次运行上面的例子,得到的结果便是
true
true
总结:
Integer的值缓存是为了在很多情况下,integer的值可能会应用在很多表示状态的值,例如:0-否,1-是; 1-未开始,2-进行中,3-已结束,这些场景下程序的性能都可以得到提升。为了避免踩坑,在包装类型间的相等判断建议用equals去比较,而不是 ==
上一篇: 类与对象的概念