Java 中 == 与 equals() 的区别

Java 中 ==equals() 的区别

1. 一句话总结

  • ==基本类型比值引用类型比地址(判断是否指向堆中同一个对象)。
  • equals():是一个方法。默认实现(Object 类)也是比地址 ;但 String、包装类等通过重写 实现了内容/逻辑相等的比较。

核心金句== 判断"是不是同一个";equals() 判断"长得像不像"(取决于是否重写)。


2. 核心区别对比表

特性 == equals()
本质 Java 运算符 Object 类的方法
比较内容 基本类型比数值 ,引用类型比内存地址 默认比地址 ,重写后比对象内容
可定制性 不可重写,行为固定 可以重写,自定义逻辑相等规则
适用范围 任何基本类型或对象引用 仅限对象(不能用于基本类型)
null 处理 null == null 为 true null.equals(...) 会抛 NPE

3. == 的用法

3.1 基本类型比较(比较值)

java 复制代码
int a = 10;
int b = 10;
System.out.println(a == b); // true

char c1 = 'A';
char c2 = 'B';
System.out.println(c1 == c2); // false

3.2 引用类型比较(比较地址)

java 复制代码
String s1 = new String("Java");
String s2 = new String("Java");
String s3 = s1;

System.out.println(s1 == s2); // false(不同对象)
System.out.println(s1 == s3); // true(同一引用)

4. equals() 的用法

4.1 默认行为:Object.equals() 等同于 ==

java 复制代码
public boolean equals(Object obj) {
    return (this == obj);
}

4.2 重写后的行为:比较内容/逻辑相等

String 重写了 equals(),比较字符串内容:

java 复制代码
String s1 = new String("Java");
String s2 = new String("Java");

System.out.println(s1.equals(s2)); // true

5. 进阶高频考点(建议必背)

5.1 字符串常量池(String Pool)

面试常考:为什么 a == b 有时是 true,有时是 false?

java 复制代码
String a = "abc";
String b = "abc";
String c = new String("abc");

System.out.println(a == b);       // true(常量池同一对象)
System.out.println(a == c);       // false(new 在堆上创建新对象)
System.out.println(a.equals(c));  // true(内容相等)

补充:

java 复制代码
String d = c.intern();
System.out.println(a == d); // true(intern 返回常量池引用)

5.2 包装类缓存机制(Integer Cache)

IntegerShortByteCharacterLong(部分范围)存在缓存机制。

java 复制代码
Integer x = 127;
Integer y = 127;
Integer m = 128;
Integer n = 128;

System.out.println(x == y);      // true  (缓存 -128~127)
System.out.println(m == n);      // false (超出缓存范围)
System.out.println(m.equals(n)); // true

结论 :比较包装类型的值,优先用 equals()(或拆箱成基本类型再比 ==,注意 null 拆箱会 NPE)。

5.3 equals()hashCode() 的契约(HashMap/HashSet 面试点)

  • 两个对象如果 equals()true,那么它们的 hashCode() 必须相同
  • HashMap/HashSet 的基本流程:hashCode() 定位桶,再 equals() 精确比较
  • 如果只重写 equals() 不重写 hashCode():可能出现"放得进去、取不出来"或"重复放入"的问题。

6. equals() 正确重写规则(契约)

  1. 自反性x.equals(x) 必须为 true
  2. 对称性x.equals(y)truey.equals(x) 也为 true
  3. 传递性x.equals(y)y.equals(z)truex.equals(z) 必须为 true
  4. 一致性:对象状态不变时,多次调用结果一致。
  5. 非空性x.equals(null) 必须为 false

7. instanceof 还是 getClass()?(加分点)

  • getClass():要求必须同一具体类才相等,更严格,较不易破坏对称性。
  • instanceof:允许子类参与比较,更灵活,但继承体系下容易破坏对称性/传递性。

8. null 安全:避免 NPE 的写法(实用)

8.1 容易出错

java 复制代码
String s = null;
System.out.println(s.equals("a")); // NPE

8.2 推荐写法

java 复制代码
String s = null;
System.out.println("a".equals(s)); // false

或:

java 复制代码
System.out.println(java.util.Objects.equals(s, "a")); // false(null-safe)

9. 一个规范的重写示例(可背模板)

java 复制代码
import java.util.Objects;

public class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

10. 什么时候用 ==?什么时候用 equals()?(面试收尾)

  • 基本类型:用 ==
  • 判断两个引用是否指向同一对象:用 ==
  • 判断对象内容(业务逻辑相等):用 equals()(并确保类正确重写 equals/hashCode)。
  • 比较 enum推荐使用 ==(枚举天然单例,且语义明确)。

11. 常见追问补充(可选)

  1. StringBuilder / StringBufferequals() :没有重写,仍是地址比较;要比内容用 toString()
  2. 数组的 equals() :数组没有重写 equals(),比较地址;比内容用 Arrays.equals() / Arrays.deepEquals()
  3. 浮点数比较== 可能因精度误差不可靠,业务上常用误差范围(epsilon)比较。
相关推荐
冬夜戏雪1 小时前
腐烂橘子/课程表 相关
java
番茄去哪了1 小时前
苍穹外卖day07---Redis缓存优化与购物车功能实现
java·数据库·ide·spring boot·spring·maven·mybatis
毕设源码-钟学长2 小时前
【开题答辩全过程】以 国产汽车的在线销售系统为例,包含答辩的问题和答案
java
亓才孓2 小时前
【MyBatis Plus】Wrapper接口
java·开发语言·数据库·spring boot·mybatis
tianzhiyi1989sq2 小时前
C++工具库之PugiXML使用指南
java·数据库·c++
毕设源码-钟学长2 小时前
【开题答辩全过程】以 哈尔滨市小酒窝APP为例,包含答辩的问题和答案
java
人道领域2 小时前
MyBatisPlus高效开发实战指南
java·开发语言·数据库
AALoveTouch3 小时前
逆向利器:Frida Hook
java·python
春和景明3603 小时前
费曼学习法
java