==equals() 的区别

在 Java 中,==equals() 都可以用于比较两个值是否相等,但它们适用的类型、比较的内容和结果却有所不同。


一、== 运算符

基本概念:

  • == 是一个 运算符,用于比较 两个操作数的值是否相等

使用规则:

数据类型 比较内容
基本数据类型 比较的是
引用数据类型 比较的是 内存地址(即对象引用)

举例说明:

int a = 100;
int b = 100;
System.out.println(a == b); // true,值相等

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false,两个不同的对象,地址不同

String s3 = "hello";
String s4 = "hello";
System.out.println(s3 == s4); // true,字符串常量池中引用的是同一对象

二、equals() 方法

基本概念:

  • equals()Object 类 提供的方法,用于判断两个对象是否“相等”。
  • 默认实现(在 Object 类中)是 比较对象的地址(即:this == obj

方法签名:

public boolean equals(Object obj)

用法与重写:

  • 若一个类没有重写 equals(),则其效果与 == 相同;
  • 若类重写了 equals(),则可自定义比较逻辑(如按值、按字段比较)。

Object 类中的 equals 源码:

public boolean equals(Object obj) {
    return (this == obj); // 默认是地址比较
}

三、实际对比说明

示例代码:

String a = new String("ab"); // 在堆中创建新对象
String b = new String("ab"); // 在堆中创建新对象
String aa = "ab"; // 在字符串常量池中
String bb = "ab"; // 指向常量池中的同一个对象

System.out.println(a == b);          // false,堆中两个不同对象
System.out.println(a.equals(b));     // true,String重写了equals,比较内容
System.out.println(aa == bb);        // true,常量池中同一对象
System.out.println(a == aa);         // false,堆对象 ≠ 常量池对象
System.out.println(42 == 42.0);      // true,int 自动转换为 double 后值仍相等

四、String 类中 equals() 的实现

String 类重写了 equals() 方法,使得其比较内容而不是地址:

源码:

public boolean equals(Object anObject) {
    // 第一步:检查是否是同一个对象引用(快速路径)
    if (this == anObject) {
        return true;
    }
    
    // 第二步:检查对象是否为String类型(类型检查)
    if (anObject instanceof String) {
        // 类型安全转型
        String anotherString = (String)anObject;
        
        // 第三步:获取当前字符串的长度
        int n = value.length;
        
        // 第四步:比较字符串长度(关键优化)
        // 如果长度不同则必然不相等
        if (n == anotherString.value.length) {
            // 第五步:获取字符数组引用
            char v1[] = value;        // 当前字符串的字符数组
            char v2[] = anotherString.value;  // 比较字符串的字符数组
            
            int i = 0;
            // 第六步:逐个字符比较
            // 使用自减计数器的循环(效率优化)
            while (n-- != 0) {
                // 发现不同字符立即返回false
                if (v1[i] != v2[i])
                    return false;
                i++;  // 移动到下一个字符
            }
            // 第七步:所有字符匹配返回true
            return true;
        }
    }
    // 第八步:对象不是String类型或长度不同返回false
    return false;
}

小结:

  • 同引用:立即返回 true
  • 非 String 类型:返回 false
  • 逐字符比较内容:若完全一致,则返回 true

五、equals() 的两种使用场景

是否重写 equals() 行为描述
没有重写 等价于 ==,比较地址
重写了 比较对象字段内容(如字符串、集合等)

六、总结对比表

比较项 == equals()
类型 运算符 方法(Object类继承)
适用对象 基本类型和引用类型 只能用于对象
基本类型行为 比较值 不适用
引用类型行为 比较内存地址 默认比较地址,重写后可自定义内容比较
是否可重写 不可 可由子类重写
常用于 判断是否同一个对象 判断两个对象内容是否相等
String默认行为 比较引用地址 比较字符串值(内容)

七、使用建议

  • 判断值是否相等:使用 equals(),特别是 String、包装类、集合等。

  • 判断是否为同一对象引用:使用 ==

  • 判断 null 前应先反向调用:

    if ("abc".equals(s)) // 推荐:避免空指针异常
    
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐