一文搞懂 == 与 equals


在讲 == 与 equals 之前,不妨先做一道题,看下下面这段代码的输出结果是什么?

/**
 * @author Woo_home
 * @create by 2020/3/18
 */

class Student {
    private String name;
    public Student(String name) {
        this.name = name;
    }
}

public class TestEquals {
    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));

        Set<String> stringSet = new HashSet<>();
        stringSet.add(s1);
        stringSet.add(s2);
        System.out.println(stringSet.size());

        System.out.println("--------------------------");

        Student student1 = new Student("abc");
        Student student2 = new Student("abc");
        System.out.println(student1 == student2);
        System.out.println(student1.equals(student2));

        Set<Student> studentSet = new HashSet<>();
        studentSet.add(student1);
        studentSet.add(student2);
        System.out.println(studentSet.size());
    }
}

OK,相信你们都已经做出来了,来对下答案,如下:
在这里插入图片描述
虚线以上的相信大部分人都能作对,但是虚线以下的就会有点不一样了。一开始我也做错了虚线以下的,那么就来探个究竟

==

先看下下面这个代码,== 即可以比较基本类型也可以比较引用类型。如果比较基本类型,如果比较的是基本类型,则比较的是值是否相等;如果比较的是引用类型,则比较的是地址是否相等
在这里插入图片描述
再来看下下面这段代码,new 出来的肯定是引用类型,存放在堆里
在这里插入图片描述
既然是在堆里的就不能跟同一个对象共用一个地址,所以下面这段代码输出的是 false
在这里插入图片描述

equals()

equals() 是 Object 类的方法,因为 Object 是所有类的父类,也就是说在 Java 里面任何一个类都有 equals() 方法

那么坦白地说 equals() 比较什么呢?

答案是:不一定

那么如果是面试被问到 equals 比较什么怎么回答呢?

  • equals() 是否被重写过,如果没有被重写过,则这个 equals 就想等于 = =,重写过后要具体问题具体分析。如下图是 Object 的 equals() 的源码,可以发现 Object 的 equals() 方法使用的是 ==
    在这里插入图片描述
    那么下面这段代码的就很好理解了,我们点击 equals() 方法跳转的是 Object 的equals() 方法。因为我们的 Student 类并没有重写 Object 的 equals 方法,所以相当于使用了 == ,所以输出的是 false
    在这里插入图片描述
    上面那个好理解,那么下面这个为什么输出的是 true 呢?同样地,我们点击 equals() 方法的源码
    在这里插入图片描述
    跳转的是 String 重写 Object 的 equals() 方法
    在这里插入图片描述

HashSet 的 add() 方法

OK,前面两个都搞懂了,还有 HashSet 的,下面的代码一个输出是 1,一个输出是 2
在这里插入图片描述
在这里插入图片描述

关于 HashSet 不会的朋友请看这里 深入理解 HashSet,关于 HashSet 看过这篇文章的朋友都知道,HashSet 底层其实是 HashMap,而且 HashSet 是不会存储相同的元素的。由于 HashSet 底层使用的是 HashMap,所以我们也可以知道 HashSet 的 add 是调用 HashMap 的 put 方法,如下:
在这里插入图片描述
那么问题来了,HashMap 我们都知道是一个 Key、Value 类型的一个类,需要传入两个东东,而 HashSet 是 add 单个东东。数量不匹配,这怎么实现的呢?

从 HashSet 的 add() 方法我们可以发现,传入的对象就是 HashMap 的 Key,而 Value 则是一个 Object 对象,也就是说 Value 不是很重要,重要的是 Key

在这里插入图片描述
在这里插入图片描述
由于 HashSet 是不允许存储重复的元素的(会被覆盖掉),那么 HashSet 是怎么判断 add 的是不是同一个对象呢?

靠的是 hashCode 的值

因为 String 重写了 hashCode() 的方法,所以先看下 String 的 hashCode() 方法
在这里插入图片描述
而 Student 这个类并没有,而是使用父类 Object 的 hashCode() 方法,如下:
在这里插入图片描述
那么这就很简单了,原来 HashSet 不允许出现重复元素是根据 hashCode() 来区分的,那么我们也将上述代码打印成 hashCode() 对比下

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.hashCode() + "\t" + s2.hashCode());

Student student1 = new Student("abc");
Student student2 = new Student("abc");
System.out.println(student1.hashCode() + "\t" + student2.hashCode());

输出:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值