public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Integer实现了三种valueOf
方法(一个底层实现,两个重载),valueOf(String s, int radix)
和
valueOf(String s)
都是优先调用parseInt(s,radix)
,无非就是十进制解析或者其它进制解析返回响应int数值,关于parseInt方法分析见另一篇博文:传送门
其实最终的调用都是valueOf(int i)
方法。我们看到方法第一行是断言一个IntegerCache
类的high
属性大于等于127。我们先跳过IntegerCache
相关这段,看最终的返回return new Integer(i);
我们之前看到Integer(int value)
构造方法其实就是将成员变量(属性property)value
设置为传入值。
现在我们回到IntegerCache
,从语义上看这段代码的意思大概是,当传入int值位于IntegerCache
的成员变量low
和high
之间时,直接返回IntegerCache.cache[i + (-IntegerCache.low)]
:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
其实IntegerCache
是Integer的一个私有静态内部类,它声明了三个静态不可变成员变量,int类型low
与high
,Integer类型cache
数组,low初始化为-128。然后其核心是一个static
静态块。
我们依然先跳过integerCacheHighPropValue
相关这段,那么代码如下:
int h = 127;
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
先初始化high = 127;
然后初始化cache为high - low + 1
大小的Integer数组,也就是cache的大小为low~high的跨度+1,为什么这里不用127 - (-128) + 1 = 256,因为我们还没考虑integerCacheHighPropValue
,从上面的代码可以看到h也可能是其它值。接下来,初始化一个int变量j,它的值是low = -128
,接着开始在high - low + 1
范围大小内循环遍历,依次为cache[k]赋值,从等式来看,cache最终也就是-128 ~ 127(h=127情况),意思说Integer将-128 ~ 127缓存下来了。
这时我们回到integerCacheHighPropValue
也就容易明白了。Integer缓存的数值范围上限提供了自定义配置方式,只是如果这个上限小于127的情况,它主动帮你调优为127,如果大于127的情况,那它保证你的上限值不超过int类型最大值。
现在我们再回到valueOf(int i)
方法,当我们想要将一个int数值转为Integer类时,如果int参数值在Integer缓存中,那么直接返回与该int参数值对应的缓存Integer对象,也就省去了Integer对象创建的开销。
我们小结一下,当我们想将int转Integer时,Integer缓存了-128 ~ 127数值,为之后的频繁调用节省了对象创建的开销,因为-128 ~ 127可能是我们最常用的数值。也因此有一个有趣的问题:
Integer integer1 = 1;
Integer integer2 = 1;
Integer integer3 = -129;
Integer integer4 = -129;
Integer integer5 = 128;
Integer integer6 = 128;
System.out.println(integer1 == integer2);
System.out.println(integer3 == integer4);
System.out.println(integer5 == integer6);
打印如下:
true
false
false
很显然符合我们上述Integer缓存策略,1是缓存范围内,所以返回了同一个对象实例,而-129和128刚好超出了缓存范围,所以返回的是new Integer(int i)
两个不同的对象实例。
当然,在判断两个Integer对象是否相等情况,我们期望的是value
值相等,还是使用equals
方法。