Integer类的缓存机制

Onida ·
更新时间:2024-11-11
· 792 次阅读

存在下述例子,判断其输出结果。

public class Main{ public static void main(String[] agrs){ Integer a = 110; Integer b = 110; Integer c = 150; Integer d = 150; System.out.println("a == b: " + (a == b)); System.out.println("c == d: " + (c == d)); } }

我们知道,在Java中存在基本数据类型和引用数据类型,而Integer作为int的封装类,Integer实例化的对象应是引用数据类型。所以,也许新手会认为是下述结果:

a == b: false c == d: false

但是,通过运行可以发现,程序输出结果是:

a == b: true c == d: false

原因
我们知道,在直接对一个Integer对象赋值时,会调用java.lang.Integer#valueOf(int i)方法 (可以通过断点的方式验证),该方法源码如下:

/** * Returns an {@code Integer} instance representing the specified {@code int} * value. If a new {@code Integer} instance is not required, this method should * generally be used in preference to the constructor {@link #Integer(int)}, as * this method is likely to yield significantly better space and time * performance by caching frequently requested values. * * This method will always cache values in the range -128 to 127, inclusive, and * may cache other values outside of this range. * * @param i * an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { // 通过if判断,可以知道,会先判断i的范围是否在IntegerCache缓存数组中, // 若存在则直接返回已缓存的实例,提高程序性能, // 若不存在,则通过 new Integer(i) 实例化返回。 if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }

根据源码注释,可知:会返回一个指定的int值的Integer实例。若不需要一个新的Integer实例,会优先采用该方法实例化,而不是new Integer(int i)。因为相比于使用new Integer(int i)的方法实例化对象,valueOf(int i)会缓存经常请求的值 (多次请求会从缓存中获得),从而获得更好的空间和时间性能。
通过阅读源码,发现Integer类中存在一个静态内部类IntegerCache,源码如下:

/** * Cache to support the object identity semantics of autoboxing for values * between -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache may be * controlled by the {@code -XX:AutoBoxCacheMax=} option. During VM * initialization, java.lang.Integer.IntegerCache.high property may be set and * saved in the private system properties in the sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; // final修饰,不可变,仅在第一次使用时初始化 static { // high value may be configured by property // 可以通过属性设置high上限值 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 = 127; } private IntegerCache() { } }

根据源码上方的注释,该类默认缓存值在[-128, 127]内的Integer对象,且采用一个final修饰的数组cache作为存储容器,首次使用时会初始化该缓存。此外,缓存的上限是可以修改的,通过修改选项:-XX:AutoBoxCacheMax=来设置缓存上限值。
其他缓存对象
不止是Integer类,其他整数类型的类都存在类似的缓存机制。
如:
ByteCache缓存Byte对象;
ShortCache缓存Short对象;
LongCache缓存Long对象;
CharacterCache缓存Character对象;
对于Byte、Short、Long、Character的缓存范围是固定的,不可修改,其中:
Byte、Short、Long的缓存范围为[-128, 127];
Character的缓存范围是[0, 127]
总结

综上所述,对Integer赋值[-128, 127],会使用Integer类的静态内部类IntegerCache返回缓存实例,且该上限值是可以自定义的,一般情况下都是采用默认值。


作者:wadreamer



INTEGER 缓存

需要 登录 后方可回复, 如果你还没有账号请 注册新账号