为什么Integer缓存-128 ~ 127

背景

面试题, 相关问题的考察.

题目大概是, 包装类型Integer == 比较的时候 : -127 ~ 128 是否相等.

其他是否相等?

原理

== 比较的是地址. 如果是不同的对象, 那么就不相等.

实践

下面是几个简单实践.

全部新建对象

解释: 新建对象后, 地址不同, 所以都是false

不新建对象

暂时的理解: -127 ~ 128 比较的对象的缓存

一些思考

时间多, 一些灵感

为什么设计这个缓存

HotSpot 团队研究, 90% 以上的整型使用落在 -128~127范围内(2000年代初期数据).

缓存范围 -128~127共 256 个对象 ≈ 4KB 内存(每个 Integer对象约16B)

为什么不多缓存一点

扩大到 -256~255则需 512 对象 ≈ 8KB,收益递减

冷知识: 上限值可以调整

部分源码如下:

java 复制代码
// IntegerCache 源码片段(OpenJDK 17)
private static class IntegerCache {
    static final int low = -128; // 硬编码下限
    static final int high;
    static {
        high = java.lang.Integer.getInteger(
            "java.lang.Integer.IntegerCache.high", 127);
        // 上限可通过VM参数调整
    }
}

为什么下限值不能自定义呢?

防止滥用:若允许下限调至 -1,000,000,可能导致缓存占用数百MB内存

其实其他包装类型也有缓存

缓存范围如下:

缓存范围 可调性
Integer -128~127 仅上限可调
Long -128~127 完全不可调
Short -128~127 完全不可调
Character 0~127(ASCII范围) 完全不可调

这个居然也是API?

Integer b = new Integer(100); // ⚠️ 已弃用API

9版本被弃用了: 神奇!

java 复制代码
/**
 * @deprecated
 * It is rarely appropriate to use this constructor. 
 * Use {@link #valueOf(int)} to take advantage of caching.
 */
@Deprecated(since="9")
public Integer(int value) {
    this.value = value;
}

设计思想

这种设计体现了 Java "80/20法则" 的工程哲学------用最小成本解决大多数问题。