Java 的包装类型的缓存机制

274 阅读2分钟

Java中基本类型都有对应的包装类分别有:ByteShortIntegerLongFloatDoubleCharacterBoolean。而它们大部分都用到了缓存机制来提升性能。Byte,Short,Integer,Long 这 4 种包装类默认创建了数值  [-128,127]  的相应类型的缓存数据,Character 创建了数值在  [0,127]  范围的缓存数据,Boolean 直接返回 True or False

Integer缓存源码

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() {}
}

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

Character缓存源码

private static class CharacterCache {
    private CharacterCache(){}

    static final Character cache[] = new Character[127 + 1];

    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Character((char)i);
    }
}

public static Character valueOf(char c) {
    if (c <= 127) { // must cache
        return CharacterCache.cache[(int)c];
    }
    return new Character(c);
}

Boolean缓存源码

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

由源码可见,超出范围了仍然会创建对象,缓存的范围区间的大小只是在性能和资源之间的权衡。 FloatDouble没有缓存机制

举例

Integer i1 = 33;
Integer i2 = 33;
/*直接是使用的缓存中的对象*/
System.out.println(i1 == i2);// 输出 true

Float i11 = 333f;
Float i22 = 333f;
/*Float没有缓存机制*/
System.out.println(i11 == i22);// 输出 false

Double i3 = 1.2;
Double i4 = 1.2;
/*Double没有缓存机制*/
System.out.println(i3 == i4);// 输出 false

Integer i5 = 127;
Integer i6 = new Integer(127);
/*i5是用的缓存中的对象,i6是直接创建的对象*/
System.out.println(i5 == i6); //输出false

Integer i7 = 128;
Integer i8 = new Integer(128);
Integer i9 = 128;
System.out.println(i7 == i8); //输出false
/*i7、i9超出 -128~127 的范围了,都是创建的对象*/
System.out.println(i7 == i9);  //输出false

谨记: 所有包装类型之间的值比较,尽量都要用equals

原文链接: Java Guide 包装类型的缓存机制了解么?