Java面试题 — Java中的==和equals()方法有什么区别?

0 阅读3分钟

Author : Cyan_RA9
Source : 【卡码笔记】网站
Question : Java中的==和equals()方法有什么区别?

【简要回答】

  • 使用"=="进行比较
    1. ==是一个比较运算符,既可以判断基本类型,又可以判断引用类型。
    2. 如果判断基本类型,判断的是二者的是否相等(eg : 判断1 == 1,结果为true;判断1 == 3,结果为false);
    3. 如果判断引用类型,判断的是二者的地址是否相同,即判定是否为同一对象(eg : Student student1 = new Student();,Student student2 = student1;判断student2 == student1,结果为true)。
  • 使用equals()方法进行比较
    1. equals()方法是顶层父类Object类中的方法,equals方法本身在Object类中的源码如下 :

      public boolean equals(Object obj) {
      	return (this == obj);
      }
      
    2. 可以看到,Object类中的 equals 方法用来检测两个对象是否相等,即默认情况下比较的是两个对象的引用(地址)。这一点和 == 用于判断引用类型时一致。

    3. equals的特点在于,它是Object类中的方法,因此,equals方法往往在子类中被重写,例如在String类中,equals方法被重写去判断两个字符串的内容是否相等。并且,在我们自己创建的类中,equals方法也常常被重写,去判断两个对象的指定的具体内容是否一致。

    4. 还有一点要注意,“==”的运行速度通常比“equals方法”更快;因为==比较引用类型时,仅比较地址;而equals方法的性能要取决于具体实现。


【详细回答】

一、使用"=="进行比较

  • 基本类型比较:直接比较两个变量的是否相等。

    int temp_a = 10;
    int temp_b = 10;
    System.out.println(temp_a == temp_b); // true
    
  • 引用类型比较:比较两个对象的内存地址是否相同(即是否为同一对象)。

    Object obj1 = new Object();
    Object obj2 = obj1;
    System.out.println(obj1 == obj2); // true(同一对象)
    System.out.println(new Object() == new Object()); // false(不同对象)
    

二、使用equals()方法进行比较

  • 默认行为: Object类中的 equals()方法 默认比较对象的地址,与 == 在进行引用类型比较时行为一致,equals方法本身在Object类中的源码如下 :

    public boolean equals(Object obj) {
    	return (this == obj);
    }
    
  • 子类重写: 大多数类会 重写 equals() 以比较对象的内容而非地址。eg:

    1. String类:比较字符串的字符序列。

      String s1 = new String("Hello");
      String s2 = new String("Hello");
      System.out.println(s1 == s2);       // false(地址不同)
      System.out.println(s1.equals(s2));  // true(地址不同但内容相同)
      
    2. Integer类:比较整数值。

    3. 自定义类:按照实际业务逻辑手动重写 equals()方法,比较指定内容。


【知识拓展】

== 和 equals 的jvm示意图

  1. 使用==进行比较的 内存图解
    double_parallel_lines_demonstration.jpg
  2. 使用equals()进行比较的 内存图解
    equals_demonstration.jpg

重写 equals()的注意事项

  1. 遵守 equals() 契约

    • 自反性:a.equals(a) 必须为 true
    • 对称性:若 a.equals(b)true,则 b.equals(a) 必须为 true
    • 传递性:若 a.equals(b)b.equals(c)true,则 a.equals(c) 必须为 true
    • 一致性:多次调用 a.equals(b) 结果应一致(除非对象被修改)。
    • 非空性:a.equals(null) 必须为 false
  2. 必须同时重写hashCode(): 若两个对象通过 equals()方法 比较为 true,则它们的 hashCode() 必须相同。代码演示如下:

    @Override
    public int hashCode() {
        return Objects.hash(name, age); // 使用相同字段生成哈希值
    }
    
  3. 正确处理 null 和 对象类型: 在 equals()方法中 需检查参数是否为 null 或对象类型是否匹配。代码演示如下:

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj; // 强制类型转换
        return age == person.age && Objects.equals(name, person.name);
    }
    
  4. Objects.equals() 静态方法源码如下:

    public static boolean equals(Object a, Object b) {
    	return (a == b) || (a != null && a.equals(b));
    }