当前位置: 首页 > news >正文

Java中的 “128陷阱“

目录

一、先明确:基本类型与包装类的区别

二、“128 陷阱” 的根源:Integer 缓存机制

三、代码示例:直观感受 “陷阱”

四、为什么会有这个缓存?

五、类似 “陷阱” 的其他包装类

六、如何避免 “陷阱”?

总结


        当我们使用Integer类型比较两个值时,若两个相同的数字(假设都为66)都在-128-127范围内,使用“==”进行比较时,结果为true;但是两个数字一旦数字大于等于128,那么再次进行比较时,结果为false。

        Java 的 “128 陷阱” 本质是 Integer 包装类的缓存机制导致的数值比较异常,核心与 Integer 类的 valueOf 方法缓存策略相关,以下是具体拆解:

一、先明确:基本类型与包装类的区别

  • int:基本类型,存储具体数值,比较时用 == 直接对比值。
  • Integerint 的包装类,是对象类型,用 == 对比的是对象的内存地址(而非值),值对比需用 equals() 方法。

        但实际开发中,用 Integer a = 123 这种 “自动装箱” 语法时,Java 会隐式调用 Integer.valueOf(123) 创建对象 —— 而 “128 陷阱” 就藏在这个方法里。

二、“128 陷阱” 的根源:Integer 缓存机制

        为了优化性能,Java 在 Integer 类中预设了一个缓存池,缓存了 -128 ~ 127 范围内的 Integer 对象
当调用 Integer.valueOf(n) 时:

  • 若 n 在 -128 ~ 127 之间:直接返回缓存池中的已有对象(Integer对象,且不会新建);
  • 若 n 超出这个范围:新建一个 Integer 对象返回。

三、代码示例:直观感受 “陷阱”

public class Integer128Demo {public static void main(String[] args) {// 1. 数值在 -128~127 范围内:缓存生效,返回同一对象Integer a = 127; // 等价于 Integer.valueOf(127)Integer b = 127;System.out.println(a == b); // true(地址相同,缓存复用)System.out.println(a.equals(b)); // true(值相同)// 2. 数值超出范围(如 128):缓存不生效,新建对象Integer c = 128; // 等价于 Integer.valueOf(128)Integer d = 128;System.out.println(c == d); // false(地址不同,两个新对象)System.out.println(c.equals(d)); // true(值相同)// 3. 手动 new 对象:无论数值是否在范围内,都新建对象(不走缓存)Integer e = new Integer(127);Integer f = new Integer(127);System.out.println(e == f); // false(两个不同对象)}
}

四、为什么会有这个缓存?

  • 性能优化-128 ~ 127 是日常开发中最常用的整数范围(如年龄、分数、索引等),缓存这些对象可以避免频繁创建 / 销毁小整数对象,减少内存开销,提升效率。
  • 设计依据:这个范围是 Java 官方根据 “常用数值分布” 确定的,且 -128 是固定下限,上限 127 可以通过 JVM 参数 -XX:AutoBoxCacheMax=<n> 自定义(如 -XX:AutoBoxCacheMax=256 可将缓存上限扩展到 256)。

五、类似 “陷阱” 的其他包装类

除了 Integer,Java 中还有其他包装类也有类似缓存机制(范围不同):

  • Byte:缓存 -128 ~ 127(全部可能值,因为 byte 范围就是这么大);
  • Short:缓存 -128 ~ 127
  • Long:缓存 -128 ~ 127
  • Character:缓存 0 ~ 127(ASCII 码范围内的字符);

FloatDouble 没有缓存(因为浮点数在任意范围内都有无限多个,缓存无意义)。

六、如何避免 “陷阱”?

        核心原则:包装类对比值时,永远用 equals() 方法,而非 ==
        即使数值在缓存范围内,也不要依赖 == 对比 —— 避免因范围变化(如自定义缓存上限)或代码修改(如从 127 改成 128)导致隐藏 bug。

// 正确写法:用 equals() 对比包装类的值
Integer x = 128;
Integer y = 128;
if (x.equals(y)) { // true,正确对比值System.out.println("值相同");
}// 注意:若可能为 null,需先判空(避免 NullPointerException)
Integer z = null;
if (z != null && z.equals(x)) { // 业务逻辑
}

总结

  • “128 陷阱” 不是 bug,而是 Java 为优化性能设计的缓存机制导致的 “直觉不符” 现象;
  • 本质是:-128~127 的 Integer 复用缓存对象,超出范围则新建对象,用 == 对比地址会出现异常结果;
  • 解决方案:包装类对比值用 equals(),基本类型对比用 ==

http://www.dtcms.com/a/338388.html

相关文章:

  • vue从入门到精通:轻松搭建第一个vue项目
  • go语言条件语if …else语句
  • rem 响应式布局( rem 详解)
  • 鼠标右键没有“通过VSCode打开文件夹”
  • FreeRTOS【3-1】创建第一个多任务程序复习笔记
  • STM32驱动SG90舵机全解析:从PWM原理到多舵机协同控制
  • Sring框架-IOC篇
  • ​​Java核心知识体系与集合扩容机制深度解析​
  • JavaSE高级-02
  • JDBC的使用
  • 【Python】Python Socket 网络编程详解:从基础到实践​
  • Street Crafter 阅读笔记
  • IDEA创建项目
  • MYSQL中读提交的理解
  • MySQL新手教学
  • lesson41:MySQL数据库进阶实战:视图、函数与存储引擎全解析
  • springBoot启动报错问题汇总
  • OVS:ovn是如何支持组播的?
  • LwIP 核心流程总结
  • wishbone总线
  • thinkphp8:一、环境准备
  • c++26新功能—可观测检查点
  • torch.nn.Conv1d详解
  • C++最小生成树
  • 高等数学 8.5 曲面及其方程
  • Python打卡Day45 预训练模型
  • 【加密PMF】psk-pmk-ptk
  • 【168页PPT】IBM五粮液集团数字化转型项目实施方案建议书(附下载方式)
  • 块体不锈钢上的光栅耦合表面等离子体共振的复现
  • 九联科技UMA223-H低功耗蜂窝模组在物联网设备中的应用与价值分析