ref:https://www.cnblogs.com/TinyWalker/p/4834685.html

--------------------

编写equals方法的建议:

  1. 显示参数命名为otherObject, 稍后转化成other变量

    public boolean equals(Object otherObject)
    
  2. 检测this和otherObject是否是同一个对象的引用,是,返回true;
    if(this==otherObject){
        return true;
    }
  3. 检测otherObject是否为null, 是, 返回false;
    if(otherObject == null){
        return false;
    }
  4. 比较this和otherObject是否属于同一个类. 如果equals的语义在每个子类中有所改变,就使用getClass检测:
    if(getClass() != otherObject.getClass()){
        return false;
    }

    如果子类语义相同,使用instanceof检测:

    if(!(otherObject instanceof Employee)){
        return false;
    }
  5. 将otherObject转化为相对应的类型变量other
    Employee other = (Employee)otherObject;
    
  6. 对所需要的比较的数据域进行比较. 如果是基本数据类型,使用a==b比较; 如果是对象比较,调用Objects.equals(a, b)进行比较
    return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
    

整个流程可以参照例1;

例1:雇员对象比较

如果两个雇员对象的姓名, 薪水和雇佣一样,就认为它们相等.重写equals方法如下:


public class Employee {

    private String name;
    private double salary;
    private Date hireDay;
    ... 
    @Override
    public boolean equals(Object obj) {
        // 如果为同一对象的不同引用,则相同
        if (this == obj) {
            return true;
        }
        // 如果传入的对象为空,则返回false
        if (obj == null) {
            return false;
        }         // 如果两者属于不同的类型,不能相等
        if (getClass() != obj.getClass()) {
            return false;
        }         // 类型相同, 比较内容是否相同
        Employee other = (Employee) obj;         return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
    }

 
 

注意,比较通过Objects中静态函数equals比较两个对象是否相等.该方法源码如下:

 public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

这样,当两个对象都为null时,返回true,例如,两个Employee对象的name都为null, 返回true; 如果第一个对象不为null,则调用a.equals(Object obj)方法

常见equals方法实现错误

1-未使用@override对覆盖超类的方法进行标记.


public class Employee {
    public boolean equals(Employee other) {     return Objects.equals(name, other.name) && salary ==other.salary && Objects.equals(hireDay, other.hireDay);
}

这个方法声明的显示参数类型是Employee. 其结果并没有覆盖Object中的equals方法,而是定义了一个完全无关的方法.为了避免发生类型错误,可以使用@override对覆盖超类的方法进行标记.

2-没有同时override hashcode()函数

object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true;
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。如下:
(1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true
(2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false
如果不重写equals,那么比较的将是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等。特别指出利用equals比较八大包装对象
(如int,float等)和String类(因为该类已重写了equals和hashcode方法)对象时,默认比较的是值,在比较其它自定义对象时都是比较的引用地址
hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。
这样如果我们对一个对象重写了euqals,意思是只要对象的成员变量值都相等那么euqals就等于true,但不重写hashcode,那么我们再new一个新的对象,
当原对象.equals(新对象)等于true时,两者的hashcode却是不一样的,由此将产生了理解的不一致,如在存储散列集合时(如Set类),将会存储了两个值一样的对象,
导致混淆,因此,就也需要重写hashcode()
举例说明:


public override bool Equals(object obj)
{
if (!(obj is BalanceSheetReport expect))
return false; return this.EndSum == expect.EndSum
&& this.PreSum == expect.PreSum
&& this.SequenceId == expect.SequenceId
&& this.ProjectId == expect.ProjectId;
} public override int GetHashCode()
{
return this.PreSum.GetHashCode()
^ this.EndSum.GetHashCode()
^ this.SequenceId.GetHashCode()
^ this.ProjectId.GetHashCode();
}
 
 

Java 基础 - 如何重写equals()的更多相关文章

  1. 【Java基础】重写equals需要重写hashcode

    Object里的equals用来比较两个对象的相等性,一般情况下,当重写这个方法时,通常有必要也重写hashcode,以维护hashcode方法的常规协定,或者说这是JDK的规范,该协定声明相等对象必 ...

  2. java构造方法和重写equals

    Cell的构造函数 package Test; import java.util.Objects; public class Cell { int a; int b; public int getA( ...

  3. [转]java基础学习总结——equals方法

    一.equals方法介绍 1.1.通过下面的例子掌握equals的用法 1 package cn.galc.test; 2 3 public class TestEquals { 4 public s ...

  4. java基础学习总结——equals方法

    一.equals方法介绍 1.1.通过下面的例子掌握equals的用法 package cn.galc.test; public class TestEquals { public static vo ...

  5. 【java基础】 == 和 equals() 的区别

    ==号和equals()方法都是比较是否相等的方法,那它们有什么区别和联系呢? 首先,==号在比较基本数据类型(指的值类型)时比较的是值,而用==号比较两个对象时比较的是两个对象的地址值: int x ...

  6. java中为什么重写equals时必须重写hashCode方法?

    在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...

  7. java removeAll和重写equals、hashcode引起的性能问题

    问题背景: 上周发现了一个spark job的执行时间从原来的10-15分钟延迟到了7个小时!wtf,这是出了什么事引起了这么大的性能问题!! 立马查看job的运行日志,发现多次运行都是在某一个固定的 ...

  8. 【原创】关于java对象需要重写equals方法,hashcode方法,toString方法 ,compareto()方法的说明

    在项目开发中,我们都有这样的经历,就是在新增表时,会相应的增加java类,在java类中都存在常见的几个方法,包括:equals(),hashcode(),toString() ,compareto( ...

  9. java 中为什么重写 equals 后需要重写 hashCode

    本文为博主原创,未经允许不得转载: 1. equals 和 hashCode 方法之间的关系 这两个方法都是 Object 的方法,意味着 若一个对象在没有重写 这两个方法时,都会默认采用 Objec ...

随机推荐

  1. Python中两大神器&exec() &eval()

    一.神器1 -- 内置函数eval eval是python中的内置函数,它的作用是将字符串变为所对应的表达式,也相当于一个功能代码加双引号变为字符串,而eval又将字符串转为相应的功能,它在使用过程中 ...

  2. 46-Ubuntu-系统信息-1-date和cal查看系统时间

    序号 命令 作用 01 date 查看系统时间 02 cal calendar查看日历,-y选项可以查看一年的日历

  3. js的基本语法规范

    1.不要在同一行声明多个变量: 2.使用===/!==来比较true/false的返回值: 3.使用字面量替代new Array这种形式: 4.不要使用全局函数: 5.switch语句必须带有defa ...

  4. Linux 进程间通信 无名管道(pipe)

    无名管道: 1)只能用于具有亲缘关系的进程之间的通信(无名管道是某一个进程创建的,不像普通文件有路径,在文件系统中是不可见的,其他进程要想打开,只能通过继承的方式去打开) 2)半双工的通信模式,具有固 ...

  5. Linux下Qt调用共享库文件.so

    修改已有的pro文件,添加如下几句: INCLUDEPATH += /home/ubuntu/camera/camera/LIBS += -L/home/ubuntu/camera/camera -l ...

  6. Thymeleaf语法总结

    Thymeleaf是Spring boot推荐使用的模板引擎. 一.th属性 html有的属性,Thymeleaf基本都有,而常用的属性大概有七八个.其中th属性执行的优先级从1~8,数字越低优先级越 ...

  7. leetcode -有效的字母异位词 python&C++

    C++解题代码: class Solutiion { public: bool isAnagram(string s, string t) { ](); int n = s.length(); int ...

  8. DOM——节点操作

    节点操作  var body = document.body; var div = document.createElement('div'); body.appendChild(div); ​ va ...

  9. C++之判断字符串是否是数字

    文章转载自https://blog.csdn.net/Richard__Ting/article/details/80772174 判断是否为数字 #include <iostream> ...

  10. NX二次开发-C++time函数计时

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_ui.h> #include <t ...