杰瑞科技汇

Java中equals和==到底有啥区别?

核心区别一句话总结

  • :是一个运算符,用于比较两个变量是否相等,对于基本数据类型,比较的是“数值”;对于引用数据类型,比较的是“内存地址”(即是否指向同一个对象)。
  • equals():是一个方法(在 Object 类中定义),用于比较两个对象”或“逻辑值”是否相等,默认情况下,它和 的行为一样(比较内存地址),但很多类(如 String, Integer)都重写(Override)了这个方法,以实现自定义的“内容相等”逻辑。

详细对比表格

特性 运算符 equals() 方法
本质 运算符 Object 类中定义的方法
作用对象 - 基本数据类型 (int, double, char 等)
- 引用数据类型 (对象)
只能用于对象
- 基本类型:比较数值是否相等。
- 引用类型:比较两个对象的内存地址是否相同(即是否为同一个对象实例)。
默认情况下(Object 类中的实现),比较两个对象的内存地址是否相同。,子类通常会重写此方法,以比较对象的或状态是否逻辑相等。
能否被重写 不能。 是 Java 语言的一个固定运算符,其行为是固定的。 可以,强烈建议子类根据业务需求重写此方法。
示例 int a = 5; int b = 5; a == b; // 结果为 true
String s1 = new String("hello"); String s2 = new String("hello"); s1 == s2; // 结果为 false
String s1 = new String("hello"); String s2 = new String("hello"); s1.equals(s2); // 结果为 true
使用场景 - 比较基本类型变量(首选)。
- 快速判断两个引用变量是否指向同一个对象(性能高)。
- 需要比较两个对象的内容是否逻辑相等时(比较两个 User 对象的用户名和密码是否相同)。
- 永远不要用 来比较字符串!

代码示例与深入解释

基本数据类型

对于基本数据类型, 比较的是它们的值。

Java中equals和==到底有啥区别?-图1
(图片来源网络,侵删)
int x = 10;
int y = 10;
int z = 20;
System.out.println(x == y); // 输出: true,因为 x 和 y 的值都是 10
System.out.println(x == z); // 输出: false,因为 x 的值是 10,z 的值是 20

equals() 方法不能用于基本数据类型,因为它们不是对象,如果你尝试对一个基本类型变量调用 equals(),会编译错误。

引用数据类型(对象)

这是最容易混淆的地方,我们以 String 为例。

比较内存地址

// s1 和 s2 是两个通过 new 关键字创建的独立对象
// 它们在内存中的地址是不同的
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // 输出: false
// 解释:s1 和 s2 是两个不同的对象实例,内存地址不同。

equals() 比较内容(因为 String 重写了 equals

String 类重写了 Object 类中的 equals() 方法,使其比较的是字符串的字符序列内容,而不是内存地址。

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2)); // 输出: true
// 解释:s1 和 s2 的内容都是 "hello",equals() 返回 true。

一个重要的特例:字符串字面量

Java 为了优化性能,会字符串常量池,当你使用双引号 创建字符串时,JVM 会先检查池中是否已存在该字符串,如果存在,就直接引用;如果不存在,就创建并放入池中。

Java中equals和==到底有啥区别?-图2
(图片来源网络,侵删)
// "hello" 是字符串字面量
// JVM 只会在池中创建一个 "hello" 对象
String s1 = "hello";
String s2 = "hello";
// s1 和 s2 指向池中同一个 "hello" 对象
System.out.println(s1 == s2);     // 输出: true (内存地址相同)
System.out.println(s1.equals(s2)); // 输出: true (内容也相同)

自定义类中的 equals()(非常重要)

如果你创建自己的类,并且希望比较两个实例的内容(而不是地址),你必须重写 equals() 方法,为了遵循 Java 规范,最好也重写 hashCode() 方法(否则在使用哈希集合如 HashMapHashSet 时会出现问题)。

不重写 equals() 的情况(默认行为):

class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 没有重写 equals() 方法
}
public class Test {
    public static void main(String[] args) {
        User user1 = new User("Alice", 30);
        User user2 = new User("Alice", 30);
        System.out.println(user1 == user2);      // 输出: false,因为它们是两个不同的对象
        System.out.println(user1.equals(user2)); // 输出: false,因为 User 类没有重写 equals(),它使用 Object 类的默认实现(比较内存地址)
    }
}

重写 equals() 方法的情况(自定义内容比较):

import java.util.Objects;
class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // IDE(如 IntelliJ IDEA 或 Eclipse)可以自动生成这个方法
    @Override
    public boolean equals(Object o) {
        // 1. 检查是否是同一个对象实例
        if (this == o) return true;
        // 2. 检查参数是否为 null 或是否属于不同的类
        if (o == null || getClass() != o.getClass()) return false;
        // 3. 类型转换
        User user = (User) o;
        // 4. 比较所有关键属性
        return age == user.age && Objects.equals(name, user.name);
    }
    // 重写 equals() 后,必须重写 hashCode(),这是一个约定
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class Test {
    public static void main(String[] args) {
        User user1 = new User("Alice", 30);
        User user2 = new User("Alice", 30);
        System.out.println(user1 == user2);      // 输出: false
        System.out.println(user1.equals(user2)); // 输出: true,因为现在比较的是 name 和 age 的值
    }
}

总结与最佳实践

  1. 基本类型用 :永远用 来比较 int, double, char 等基本数据类型。
  2. 对象比较内容用 equals():当你想知道两个对象在逻辑上是否“相等”(两个 User 对象代表的是同一个人)时,使用 equals()
  3. 对象比较地址用 :当你需要确认两个引用变量是否指向完全相同的对象实例时(单例模式检查),使用 。
  4. 永远不要用 比较字符串:除非你明确想检查两个字符串变量是否指向池中同一个字面量,对于业务逻辑,99% 的情况都应该用 equals()
  5. 重写 equals() 就要重写 hashCode():这是 Java 集合框架(特别是哈希表)的硬性要求,可以避免 HashMap 等集合出现异常行为。
Java中equals和==到底有啥区别?-图3
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇