杰瑞科技汇

Java Integer 比较该用 == 还是 equals?

Integer 的比较分为三种情况,你需要根据场景选择正确的方法:

Java Integer 比较该用 == 还是 equals?-图1
(图片来源网络,侵删)
  1. 比较 Integer 对象的值是否相等 (最常用)
  2. 比较 Integer 对象的引用(内存地址)是否相同 (很少用,但有特殊场景)
  3. 比较 int 基本类型的值是否相等 (最直接)

核心概念:Integer 的装箱与拆箱

在深入比较之前,必须理解 Integerint 的区别。

  • int: 是 Java 的基本数据类型,它直接存储值,没有额外开销,存放在中。
  • Integer: 是 int 对应的包装类,它是一个对象,包含一个 int 类型的字段,对象存放在中。

Integer 对象的创建过程涉及装箱,将 int 转换为 Integer 对象,而将 Integer 对象转回 int 的过程称为拆箱

// 装箱: int -> Integer
Integer a = 10; // 编译器会自动执行 Integer.valueOf(10)
// 拆箱: Integer -> int
int b = a; // 编译器会自动执行 a.intValue()

Integer 对象的比较之所以复杂,主要因为它是一个对象,而对象比较默认是比较内存地址。


比较 Integer 对象的值是否相等 (最常用)

这是绝大多数情况下你想要做的事情,你需要判断两个 Integer 对象内部的 int 值是否相同。

Java Integer 比较该用 == 还是 equals?-图2
(图片来源网络,侵删)

✅ 正确方法:使用 .equals()

Integer 类重写了 Object 类的 equals() 方法,它的作用就是比较两个 Integer 对象的值是否相等,而不是它们的内存地址。

示例代码:

Integer num1 = new Integer(10);
Integer num2 = new Integer(10);
// 使用 equals() 比较值
System.out.println("num1.equals(num2): " + num1.equals(num2)); // 输出: true
// 也可以使用 Objects.equals() (更安全,能处理null)
System.out.println("Objects.equals(num1, num2): " + Objects.equals(num1, num2)); // 输出: true

为什么不能直接用 ? 在比较对象时,比较的是它们的内存地址(引用)new Integer(10) 会为 num1num2 在堆中创建两个不同的对象,它们的内存地址不同,num1 == num2false

Integer num1 = new Integer(10);
Integer num2 = new Integer(10);
System.out.println("num1 == num2: " + (num1 == num2)); // 输出: false

比较 Integer 对象的引用是否相同

这种情况非常罕见,通常只在需要判断两个变量是否指向同一个对象实例时使用。

Java Integer 比较该用 == 还是 equals?-图3
(图片来源网络,侵删)

✅ 正确方法:使用

运算符用于比较两个对象的引用(内存地址),如果两个引用指向堆中的同一个 Integer 对象,则返回 true

示例代码:

Integer a = new Integer(10);
Integer b = a; // b 指向 a 所指向的对象
System.out.println("a == b: " + (a == b)); // 输出: true,因为它们是同一个对象
Integer c = new Integer(10);
System.out.println("a == c: " + (a == c)); // 输出: false,因为它们是两个不同的对象

比较 int 基本类型的值是否相等

当你确定要比较的是两个基本类型 int 的值时,直接使用 即可,这是最简单、最高效的方式。

✅ 正确方法:使用

示例代码:

int x = 10;
int y = 10;
System.out.println("x == y: " + (x == y)); // 输出: true
// 当 Integer 对象被拆箱后,比较的是其基本类型的值
Integer z = 10;
System.out.println("x == z: " + (x == z)); // 输出: true,因为 z 被自动拆箱为 int 10

Integer 缓存带来的“陷阱”: 在特定情况下的“意外”成功

这是 Integer 比较中最容易让人困惑的地方,为了提高性能和减少内存占用,Integer 类提供了一个内部缓存(也称为“常量池”),范围在 -128127 之间。

当你使用 Integer i = value; 这种方式(而不是 new Integer(value))创建 Integer 对象时,value[-128, 127] 范围内,Java 不会创建新对象,而是直接从缓存中返回已经存在的对象。

示例代码:

// 在 [-128, 127] 范围内
Integer i1 = 127;
Integer i2 = 127;
// 因为 127 在缓存范围内,i1 和 i2 指向缓存中的同一个对象
System.out.println("i1 == i2 (127): " + (i1 == i2)); // 输出: true
Integer i3 = 128;
Integer i4 = 128;
// 因为 128 超出缓存范围,i3 和 i4 是两个新创建的对象
System.out.println("i3 == i4 (128): " + (i3 == i4)); // 输出: false

这个陷阱的总结:

  • new Integer(): 总是创建新对象, 比较永远为 false(值相同的情况下)。
  • Integer.valueOf(): 编译器会将 Integer a = 10; 转换为 Integer.valueOf(10)
    • 如果值在 [-128, 127], 比较可能为 true(因为指向缓存)。
    • 如果值超出范围, 比较为 false(因为创建了新对象)。
  • Integer.parseInt(): 返回的是 int 基本类型,后续比较 是比较基本类型值。

你的目标 推荐方法 示例 原因
比较两个 Integer 对象的值 使用 equals() a.equals(b)Objects.equals(a, b) 这是 Integer 类设计的正确意图,不受缓存影响,能准确比较值。
比较一个 Integer 和一个 int 使用 int a = 10; Integer b = 10; a == b; 会发生自动拆箱,比较的是两个基本类型的值,高效且正确。
比较两个 int 基本类型 使用 int a = 10; int b = 10; a == b; 最直接、最高效的比较方式。
判断两个变量是否指向同一个对象 使用 a == b 这是 的原始行为,用于比较引用地址。

一张图看懂

graph TD
    A[开始比较 Integer] --> B{你的目的是什么?};
    B -- 比较值是否相等 --> C[使用 .equals() 或 Objects.equals()];
    B -- 比较是否是同一个对象 --> D[使用 ==];
    B -- 其中一个是基本类型 int --> E[使用 == (会自动拆箱)];
    C --> F[结果是 true/false (基于值)];
    D --> G[结果是 true/false (基于内存地址)];
    E --> H[结果是 true/false (基于拆箱后的值)];
    subgraph "重要提醒"
        I[Integer 有-128到127的缓存<br>可能导致 == 比较值时出现意外结果]
    end

面试高频问题

问题: 以下代码的输出结果是什么?为什么?

Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a == b); // ?
System.out.println(c == d); // ?

答案:

  • System.out.println(a == b); 输出 true
    • 原因100Integer 的缓存范围 [-128, 127] 内。ab 都是通过 Integer.valueOf(100) 创建的,它们指向缓存中的同一个 Integer 对象, 比较引用地址为 true
  • System.out.println(c == d); 输出 false
    • 原因200 超出了缓存范围。cd 都是通过 Integer.valueOf(200) 创建的,但由于值不在缓存中,JVM 会为它们分别创建两个新的 Integer 对象,这两个对象在堆中的内存地址不同, 比较引用地址为 false

补充问题: 如果要比较 cd 的值,应该怎么写? 答案: System.out.println(c.equals(d));,这会输出 true

分享:
扫描分享到社交APP
上一篇
下一篇