包装类的 “缓存陷阱”:Integer.valueOf (128) == 128 为何为 false?

一、Bug 场景

在一个 Java 项目中,开发人员在进行整数包装类 Integer 的比较操作时,遇到了一个看似奇怪的现象。当使用 Integer.valueOf(128)128 进行 == 比较时,结果为 false,这与他们预期的结果不符,因为从逻辑上看这两个值应该相等。这个问题导致了一些依赖于正确比较结果的业务逻辑出现错误,影响了程序的正常运行。

二、代码示例

java 复制代码
public class IntegerComparisonBugExample {
    public static void main(String[] args) {
        Integer num1 = Integer.valueOf(128);
        int num2 = 128;

        System.out.println("num1 == num2 的结果: " + (num1 == num2));
    }
}

三、问题描述

  1. 预期行为 :开发人员预期 num1 == num2 的结果为 true,因为 num1 是通过 Integer.valueOf(128) 获取的 Integer 对象,而 num2 是值为 128 的基本数据类型 int,从数值角度看它们是相等的。
  2. 实际行为 :实际输出结果为 false。这是因为 Integer.valueOf() 方法存在缓存机制。在 Java 中,Integer 类对 - 128 到 127 之间的整数进行了缓存。当调用 Integer.valueOf(int i) 方法时,如果 i 的值在 - 128 到 127 这个范围内,会直接返回缓存中的对象;如果超出这个范围,则会创建一个新的 Integer 对象。在上述代码中,Integer.valueOf(128) 创建了一个新的 Integer 对象,而 num2 是基本数据类型 int。当使用 == 进行比较时,对于基本数据类型和包装类的比较,num1 会自动拆箱为 int 类型再进行比较。但由于 num1 是新创建的对象,在内存地址上与 num2 不同(即使数值相同),所以 == 比较结果为 false。如果两个 Integer 对象都是通过 valueOf 方法获取且值在缓存范围内,== 比较会返回 true,因为它们指向同一个缓存对象。

四、解决方案

  1. 使用 equals 方法 :在进行 Integerint 的比较时,始终使用 equals 方法,这样比较的是数值而不是内存地址。
java 复制代码
public class IntegerComparisonBugExample {
    public static void main(String[] args) {
        Integer num1 = Integer.valueOf(128);
        int num2 = 128;

        System.out.println("num1.equals(num2) 的结果: " + num1.equals(num2));
    }
}
  1. 了解缓存机制并谨慎使用 == :如果确实需要使用 == 进行比较,要确保两个 Integer 对象都是通过 valueOf 方法获取且值在 - 128 到 127 范围内,或者明确知道比较的是对象引用(内存地址)。例如:
java 复制代码
public class IntegerComparisonBugExample {
    public static void main(String[] args) {
        Integer num1 = Integer.valueOf(127);
        Integer num2 = Integer.valueOf(127);

        System.out.println("num1 == num2 的结果: " + (num1 == num2));
    }
}

这里由于 127 在缓存范围内,num1num2 指向同一个缓存对象,所以 == 比较结果为 true。但这种比较方式依赖于缓存机制,使用时需谨慎,避免因值超出缓存范围导致的意外结果。

相关推荐
JAVA面经实录91713 小时前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
许彰午15 小时前
CacheSQL(二):主从复制——OpLog 环形缓冲区与故障自动恢复
java·数据库·缓存
Bat U16 小时前
JavaEE|多线程初阶(七)
java·开发语言
掌心向暖RPA自动化19 小时前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa
日取其半万世不竭19 小时前
Minecraft Java版社区服务器搭建教程(Linux,适合新手)
java·linux·服务器
TeamDev19 小时前
JxBrowser 9.0.0 版本发布啦!
java·前端·混合应用·jxbrowser·浏览器控件·跨平台渲染·原声输入
AI人工智能+电脑小能手20 小时前
【大白话说Java面试题】【Java基础篇】第24题:Java面向对象有哪些特征
java·开发语言·后端·面试
AI人工智能+电脑小能手20 小时前
【大白话说Java面试题】【Java基础篇】第25题:JDK1.8的新特性有哪些
java·开发语言·后端·面试
likerhood20 小时前
SLF4J: Failed to load class “StaticLoggerBinder“ 解决
java·log4j·maven
早日退休!!!21 小时前
大模型推理瓶颈七层分析模型
java·服务器·数据库