Java 中 Integer 缓存池在 -128 到 127 范围内的设计绝非偶然,而是享元模式(Flyweight)在 JVM 层面的经典实践:通过预创建并复用少量不可变对象,以极小内存开销(仅约几十 KB)换取高频整数值的高效共享,显著提升性能与内存利用率;它依赖 valueOf() 这一标准工厂方法实现智能缓存命中,而 new Integer() 则完全绕过该机制;这一范围是经过严谨权衡的结果——兼顾常见使用场景(如状态码、索引、枚举)与缓存性价比,且仅对自动装箱和 valueOf() 生效,其他方式创建的对象均不参与共享——理解这一点,才能真正避开 == 判断陷阱,写出更健壮、更符合 JVM 设计哲学的代码。

Java 的 Integer 在 -128 ~ 127 范围内复用对象,不是巧合,而是标准享元(Flyweight)模式的实践:用少量共享对象支撑大量逻辑请求,避免重复创建。它不叫“享元类”,但行为完全符合——内部状态固定(数值不可变),外部无依赖,可安全共享。
这不是拍脑袋定的,是享元模式中“权衡共享收益与内存成本”的直接体现:
IntegerCache初始化时就预分配cache数组,长度固定为 256(-128 到 127 共 256 个值),内存开销极小(几十 KB)- 下限 -128 对齐
byte最小值,覆盖常见负数场景(如 HTTP 状态码、错误码) - 上限 127 覆盖绝大多数循环索引、数组长度、HTTP 状态码(4xx/5xx)、枚举序号等高频值
- 若扩大到 1000,缓存对象增为 1129 个,内存占用翻几倍,但命中率提升有限——享元失效
Integer.valueOf(int) 就是标准的享元工厂:查缓存、命中则返回,未命中才新建。而 new Integer(int) 强制走构造路径,彻底跳过缓存逻辑——这就像手动 new 一个 String 而不用字符串常量池。
Integer a = 100;→ 编译为Integer.valueOf(100)→ 命中缓存 → 同一对象Integer b = new Integer(100);→ 强制堆上新建 → 地址不同 →a == b为falseInteger c = 200;→valueOf(200)超出缓存范围 → 新建对象 →c == Integer.valueOf(200)仍为false
享元是否启用、范围是否可调,取决于该类型在实际使用中的“共享价值”:
Boolean只有TRUE/FALSE两个实例 → 全量缓存,且不可配置 → 共享收益 100%,成本趋近于 0Long在 JDK 源码中保留了LongCache结构,但默认未启用(cache数组为空)→ 高位长整数复用率低,享元性价比差Integer是唯一默认开启、范围可调(-XX:AutoBoxCacheMax=)、且被语言规范强制要求实现的享元 → 它是 JVM 层面公认的“高价值共享候选”
真正容易被忽略的是:缓存行为只作用于 valueOf() 及其触发的自动装箱;任何显式 new、反射构造、或反序列化产生的 Integer 都不参与享元。别假设“值一样就一定共享”。
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《享元模式解析:Integer缓存为何在-128~127优化》文章吧,也可关注golang学习网公众号了解相关技术文章。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/279880.html