一文彻底弄懂双等 “==” 和 equals 的区别,从此面试再也不会入坑了

基本数据类型:因为基本数据类型没有引用对象,所以 “==” 的效果就是比较值是否相同,基本数据类型没有 equals 方法

引用数据类型:“==” 和 equals 两者都是比较引用的对象是否相同


为什么我们在网上会看到说:双等比较引用,equals比较值呢?

那是因为equals被重写了,重写之后的效果就是比较值是否相等,那些例子都是用String类型之间进行比较的,String内部默认重写了equals方法,所以才有了以上的说法


如下是equals的源码,可以看到equals的内部实现就是 “==”

public boolean equals(Object obj) {
    return (this == obj);
}

如下是String内部重写equals的源码

  • String内部重写了equals方法,重写后的效果就是比较两个对象的值是否相等
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    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) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

对应引用数据类型来说,可以这样记:

  • 如果equals没有被重写,两种比较是相同的

  • 如果equals被重写了,那么两种比较自然不同

  • String内部默认重写了equals方法,所以:”==“ 比较引用,equals 比较值


String测试

(”==“ 比较引用,equals 比较值)

直接定义两个值相同的字符串进行比较

String str1 = "hello";
String str2 = "hello";
System.out.println(str1 ==  str2); // true
System.out.println(str1.equals(str2)); // true

在创建字符串的时候,会先创建一个字符串缓冲池

当创建str1时,先在字符串常量池中寻找有没有对应“hello”的对象,如果没有,就创建一个,然后将str1对象放入字符串常量池中,将str1的值“hello”放入常量池中

JDK1.7后:字符串常量池保存引用,常量池保存值

当创建str2时,先在字符串常量池中寻找有没有对应“hello”的对象,发现str1对应的值和自己要创建的字符串值相同,就直接引用str1所引用的对象

所以

  • str1==str2:两者引用的对象相同,都是“hello”;
  • str1.equals(str2)也相同:两者的值相同

直接定义两个值不同的字符串进行比较

String str1 = "hello";
String str2 = "hi";
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // false
  • 两者所引用的对象不同,所以 str1 == str2 肯定为false
  • 两者的值也不同,所以下面的也是false

new两个值相同的字符串进行比较

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // true

在new一个对象的时候,不会从字符串缓冲池中寻找,而是直接开辟一个新的空间来创建一个新的对象,创建的对象也不会添加到常量池中

所以

  • new了两个对象,两个对象的引用肯定不是同一个,双等的比较为false
  • 但是两个对象的值是相同的,都是“Hello”,所以equals的比较相同为 true

new两个值不同的字符串进行比较

String str1 = new String("Hello");
String str2 = new String("Hi");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // false
  • new了两个对象,两个对象的引用肯定不是同一个,双等的比较为false
  • 两个对象的值也是不相同的,所以equals的比较不同为 false

直接定义一个字符串和new一个字符串进行比较(两者值相同)

String str1 = "Hello";
String str2 = new String("Hello");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // true
  • 因为str2 new了一个新对象,所以和str1的引用不是同一个,双等的比较为false
  • 但是两者的值是相同的,所以equals的比较为 true

直接定义一个字符串和new一个字符串进行比较(两者值不同)

String str1 = "Hello";
String str2 = new String("Hi");
System.out.println(str1 ==  str2); // false
System.out.println(str1.equals(str2)); // false
  • 因为str2 new了一个新对象,所以和str1的引用不是同一个,双等的比较为false
  • 两者的值是不相同的,所以equals的比较也为 false

其它对象测试

(”==“ 比较引用,equals 也比引用)

首先创建一个实体类

class Person {
    private int id;

    public Person(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

new 两个值相同的对象

Person person1 = new Person(12);
Person person2 = new Person(12);
System.out.println(person1 == person2); // false
System.out.println(person1.equals(person2)); // false
  • 因为equals没有被重写,所以两种比较都是一样的,都为false

new两个值不同的对象

Person person1 = new Person(12);
Person person2 = new Person(25);
System.out.println(person1 == person2); // false
System.out.println(person1.equals(person2)); // false
  • 因为equals没有被重写,所以两种比较都是比较引用是否相同,和对象的值无关,所以都为false

总结

基本数据类型:因为基本数据类型没有引用对象,所以 “==” 的效果就是比较值是否相同,基本数据类型没有 equals 方法

引用数据类型:“==” 和 equals 两者都是比较引用的对象是否相同

  • equals 方法可以被重写
  • String内部默认重写了 equals 方法,使其效果为判断两者的值是否相等
  • 创建字符串时,会先在字符串常量池中进行查找
  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值