Java 中 == 与 equals()的区别笔记

==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)) // 推荐:避免空指针异常
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值