重写equals方法

简介: 我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么呢?其实是和Java底层人家写的equals方法逻辑有关系

我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么呢?其实是和Java底层人家写的equals方法逻辑有关系


equals()方法是做什么的?


英语角度:


b2b72db08e3b9a09e149ced3a799aec1.png


计算机角度:比较多个值是否相等


实战场景


先来看段代码我们脑海中有个场景吧!


User类


package StringEquals;
public class User {
    private String name;
    public User() {
    }
    public User(String name) {
        this.name = name;
    }
}


主函数


package StringEquals;
import java.util.ArrayList;
import java.util.Collection;
public class Main {
    public static void main(String[] args) {
        //实例化一个集合对象
        Collection c = new ArrayList();
        //实例化一个叫唐三的对象
        User tangsan1 = new User("唐三");
        //再次实例化一个叫唐三的对象
        User tangsan2 = new User("唐三");
        //把第一个tangsan1对象添加到集合中
        c.add(tangsan1);
        //判断集合中是否包含叫唐三的对象
        System.out.println(c.contains(tangsan2)); 
    }
}


客户端输出结果

6470c92edbe409d6a6e38e1cd219ff28.png


此时是不是就疑惑了,明明tangsan1和tangsan2这两个变量所指向的对象都叫唐三啊,集合中也有叫唐三的这个对象,那为什么在判断集合是否包含叫唐三的对象时返回false呢?这是为什么? 我们先来看看Java中底层定义的contains方法是如何进行逻辑判断的,如下图。


contains底层逻辑判断


b7f0680b2b60dd5a2ad62af763aaf145.png


通过进入到contains方法底层,发现在进行逻辑判断的时候会调用equals方法进行比较。我们通过debug单步调试进入到equals底层之后发现,如下图:


92786fd60a4c89fbd9dbed0bc30e639e.png


this==obj,这里实际上比较的是tangsan1和tangsan2这两个对象的内存地址,因为实例化时分别new了两个不同的User对象,所有tangsan1和tangsan2这两个变量实际上所存储的地址空间不同、指向的对象也不同。


内存图


我们在来画一张这个程序的内存图,看看每一个变量和对象再内存中是如何划分的,如下图:


6e624826fedc03eafd04e0446603b780.png


看出来有什么不同了吗?虽然在代码中tangsan1和tangsan2这两个变量所指向的对象都叫唐三,但是他们分别所指向的对象不同,这两个对象所指向的地址也不同。


重写equals方法


有些人可能就问了,我只想判断两个对象里面的数据是否相同,如何做?重写equals方法,代码如下:


User类


package StringEquals;
public class User {
    private String name;
    public User() {
    }
    public User(String name) {
        this.name = name;
    }
    //重写equals方法,比较连个对象里面的数据是否一致
    public boolean equals(Object o) {
        if (o == null || !(o instanceof User)) return false;
        if (o == this) return true;
        User u = (User) o;
        return u.name.equals(this.name);
    }
}


主函数


package StringEquals;
import java.util.ArrayList;
import java.util.Collection;
public class Main {
    public static void main(String[] args) {
        //实例化一个集合对象
        Collection c = new ArrayList();
        //实例化一个叫唐三的对象
        User tangsan1 = new User("唐三");
        //再次实例化一个叫唐三的对象
        User tangsan2 = new User("唐三");
        //把第一个tangsan1对象添加到集合中
        c.add(tangsan1);
        //判断集合中是否包含叫唐三的对象
        System.out.println(c.contains(tangsan2)); 
    }
}


客户端输出结果


94617f22e89a0b0f351f8a3aa6062882.png


这里我们重写了equals方法,之后在调用equals方法的时候,程序就会调用我们自己写的这个重写之后的equals方法,程序就会认为tangsan1也叫唐三,tangsan2也叫唐三,他们名字相同就是同一个人。


总结


  • 不重写:调用Objcet的equals方法,判断的是内存地址是否一致
  • 重写:调用自定义的equals方法,判断是内容是否一致
  • 存放在一个集合中的类型,一定要重写equals方法
相关文章
|
1月前
|
存储 算法 Java
为什么要重写 hashcode 和 equals 方法
为什么要重写 hashcode 和 equals 方法
22 0
|
4月前
|
存储
重写equals后为什么要重写hashcode方法
重写equals后为什么要重写hashcode方法
44 0
|
1月前
|
自然语言处理 算法 Java
为什么说重写equals时要重写hashcode
为什么说重写equals时要重写hashcode
|
1月前
|
存储 Java
为什么要重写hashCode()和equals()(深入了解)
为什么要重写hashCode()和equals()(深入了解)
|
3月前
|
存储 IDE Java
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
为什么重写 equals() 时必须重写 hashCode() 方法?(简单易理解)
17 1
|
8月前
|
存储
为什么重写 equals 方法就必须重写 hashCode 方法?
为什么重写 equals 方法就必须重写 hashCode 方法?
60 0
|
9月前
为什么要重写 hashcode 和 equals 方法?
为什么要重写 hashcode 和 equals 方法?
55 0
|
存储 算法 Java
(强制)要求覆写equals必须覆写hashCode(原理分析)
hashCode和equals hashCode和equals用来标识对象,两个方法协同工作可用来判断两个对象是否相等。众所周知,根据生成的哈希将数据散列开来,可以使存取元素更快。对象通过调用Object.hashCode()生成哈希值;由于不可避免会存在哈希值冲突 的情况,因此当hashCode相同时,还需要再调用equals进行一次值的比较;但是若hashCode不同,将直接判定Object不同,跳过equals,这加快了冲突处理效率。Object类定义中对hashCode和equals要求如下:
192 0
|
存储 Java 对象存储
JavaSE——为什么重写equals的同时一定要重写hashCode?
JavaSE——为什么重写equals的同时一定要重写hashCode?
JavaSE——为什么重写equals的同时一定要重写hashCode?

热门文章

最新文章