【实践】java.lang.Integer源码分析 -- valueOf

来源:互联网 发布:mac管理员名称是什么 编辑:程序博客网 时间:2024/05/17 02:15
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的成员变量lowhigh之间时,直接返回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类型lowhigh,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);

打印如下:

truefalsefalse

很显然符合我们上述Integer缓存策略,1是缓存范围内,所以返回了同一个对象实例,而-129和128刚好超出了缓存范围,所以返回的是new Integer(int i)两个不同的对象实例。
当然,在判断两个Integer对象是否相等情况,我们期望的是value值相等,还是使用equals方法。

0 0