Integer.valueOf源码分析

1. 引言

在牛客网上看到这样一道题目,判断一下打印的结果

public static void main(String[] args){
	    Integer i1 = 128;
        Integer i2 = 128;
        System.out.println(i1==i2);

        Integer i3 = 100;
        Integer i4 = 100;
        System.out.println(i3==i4);
    }

刚开始看到是,是这样来判断的:因为 Integer i1 = 128 这条语句,Integer 会启用自动装箱功能,调用 Integer.valueOf 方法返回一个 Integer 对象,因此这四个对象应该指向不同的地址,所以打印的结果是两个 false。但是在 eclipse 运行结果如下,为什么会这样呢?

运行结果

2. 分析

首先想到的就是 Integer.valueOf 这个方法有点蹊跷,因此就去看了一下它的源码,它的内部实现如下:

 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

从中可以看出,valueOf 方法首先会判断 i 值是否在一个范围内,如果是的话,会从 IntegerCache 的 cache(其实是一个用 final static 修饰的数组) 中返回 Integer 对象,如果不在这个范围内,会创建一个新的 Integer 对象。那么就看一下这个范围是什么吧。跟到 IntegerCache 类内部,可以看到它定义的两个变量,low 为 -128,high 还未定义。

static final int low = -128;
static final int high;

通过 ctrl+F 查找 high 是什么时候创建的,发现是在一个静态代码块里面:

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;
}

从中可以看出,high 的值是由 h 决定的,h 一般为 127。这说明,当 valueOf 传入的参数值在 -128~127 之间,这些数值都会存储在静态数组 cache 中。因此,在 valueOf 方法里,参数在 -128~127 之间,返回 Integer 对象的地址引用是一样的,对于题目也有了正确的解答。

3. 总结

刚开始学编程时,如果碰到问题时,都是把报错的信息赋值到百度或者谷歌上进行搜索,直接根据被人的踩坑经验,按照他们给的步骤来解决问题,现在我又发现了一种更高效的解决方案 -- 直接看源码,直接了解底层的实现,很快就可以解决问题了。所以,把自己的基础打牢,勿以浮沙筑高台!

posted @ 2018-08-13 11:40  firepation  阅读(761)  评论(0编辑  收藏  举报