当前位置: 首页 > 工具软件 > xcache-j > 使用案例 >

包装类valueOf()详解(xCache内部类)

公孙弘图
2023-12-01

包装类valueOf()方法中的xCache类

最近面试遇到了一道基础题。题目如下

Integer a = new Integer(120);
Integer b = new Integer(120);
System.out.println(a == b);

Integer c = 120;
Integer d = 120;
System.out.println(c == d);

Integer e = 130;
Integer f = 130;
System.out.println(e == f);

正确的输出结果应该是

false true false

首先,我们都知道 ==,基本数据类型比较的是值,引用数据类型比较的是地址值。而包装类属于引用数据类型,所以比较的是地址值。所以a==b结果为false,因为a和b都是new()出来的,是两个对象,值相同,地址值不同。

我们知道Integer c = 120; 会自动装箱,java通过Integer.valueOf(120)来实现。既然如此,为什么c==d为true而e==f为false?具体的原因就需要看valueOf()方法的源码。



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

该方法中有一个判断,如果ilowhigh之间,则从IntegerCache.cache[]中返回一个对象。否则是new一个对象。结合c==d为true,e==f为false,我们就能定位问题的关键了,在与IntegerCache中的实现逻辑。



IntegerCache源码如下:

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) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                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() {}
}

从源码中我们看到,low为-128,high默认为127。在IntegerCache中有一个静态代码块,在该类初始化时,会创建一个Integer cache[]。这里会缓存 -128~127 共计256个对象。

经过源码分析,我们已经能够明白为什么c==d为true,e==f为false了。120在-128~127之间,所以直接从Integer.IntegerCache#cache[]中获取,地址值相同。而130在-128~127之外,所以是new出的新对象,地址值也就不同。同样,这也就是为什么包装类建议使用equals()方法比较。



通过查看其它包装类的源码,我们能够发现只有部分包装类才有cache。如下表:

是否有Cache最小值最大值
Boolean
ByteByteCache-128127(固定)
ShortShortCache-128127(固定)
CharachterCharachterCache0127(固定)
IntegerIntegerCache-128127(默认,java.lang.Integer.IntegerCache.high)
LongLongCache-128127(固定)
Float
Double
 类似资料: