Java中==与equals()的区别

Java中==与equals()的区别

一、核心区别与底层原理

1. == 运算符

  • 本质作用:比较的是内存地址(或者说变量的值)。

    • 对于基本数据类型(byte/short/int/long/float/double/char/boolean):== 比较的是实际数值(因为基本类型变量直接存储值,没有地址概念)。

    • 对于引用数据类型(类 / 数组 / 接口等):== 比较的是对象在堆内存中的地址,只有两个引用指向同一个对象时,== 才返回 true

2. equals() 方法

  • 本质作用:是 Object 类中的方法,默认实现等价于 ==(比较地址),但可以被重写,用于比较对象的内容 / 属性是否相等。

    • Object 类的默认 equals() 源码:

      public boolean equals(Object obj) {
          return (this == obj); // 底层还是用==比较地址
      }
    • 常用类(如 StringIntegerDate)都重写了 equals(),改为比较内容而非地址。

二、代码示例:直观理解

示例 1:基本数据类型 vs 引用数据类型(==

public class CompareDemo {
    public static void main(String[] args) {
        // 1. 基本数据类型:== 比较数值
        int a = 10;
        int b = 10;
        System.out.println(a == b); // true(数值相等)

        // 2. 引用数据类型:== 比较地址
        String s1 = new String("Java");
        String s2 = new String("Java");
        System.out.println(s1 == s2); // false(两个不同对象,地址不同)

        // 特殊:String常量池(新手易踩坑)
        String s3 = "Java";
        String s4 = "Java";
        System.out.println(s3 == s4); // true(常量池复用同一地址)
    }
}

示例 2:equals() 方法的使用

public class EqualsDemo {
    public static void main(String[] args) {
        // 1. String类重写了equals():比较内容
        String s1 = new String("Java");
        String s2 = new String("Java");
        System.out.println(s1.equals(s2)); // true(内容相同)

        // 2. 自定义类(未重写equals()):等价于==
        Person p1 = new Person("张三", 20);
        Person p2 = new Person("张三", 20);
        System.out.println(p1.equals(p2)); // false(地址不同)

        // 3. 自定义类(重写equals()):比较属性
        System.out.println(p1.equals(p2)); // 重写后返回true
    }
}

// 自定义Person类
class Person {
    private String name;
    private int age;

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

    // 重写equals():比较name和age是否都相等
    @Override
    public boolean equals(Object obj) {
        // 1. 地址相同,直接返回true
        if (this == obj) return true;
        // 2. obj为null或类型不同,返回false
        if (obj == null || getClass() != obj.getClass()) return false;
        // 3. 强转后比较属性
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
}

三、关键注意事项

  1. 调用 equals() 时,避免空指针异常

    错误写法:String s = null; s.equals("Java");(会抛 NullPointerException)

    正确写法:"Java".equals(s);(常量非空,安全)

  2. 重写 equals() 时,建议同时重写 hashCode()

    • 这是 Java 规范要求(如 HashMap 等集合类依赖两者一致性)。

    • 核心原则:equals() 返回 true 的两个对象,hashCode() 必须相等;反之不强制。

总结

  1. ==:基本类型比数值,引用类型比内存地址,无法被修改 / 重写。

  2. equals():默认比地址,可重写为比对象内容(如 String/Integer),自定义类需手动重写才能比较属性。

  3. 实际开发中,比较对象内容优先用 equals(),比较地址 / 基本类型值用 ==

成员变量与局部变量的区别 2026-02-25