equals方法实现小记
方法 实现 小记 equals
2023-09-14 08:59:40 时间
最近做项目,在一次写equals方法时突然悟出了一些心得,小记之,以备后用。在《Effective Java(第二版)》的Item7中提出我们要尽量避免重新equals方法,他同时也列举了几种我们不需要实现equals方法的情况:
1)类的每个实例从本质上来说是唯一的,如Thread类的实例。
2)我们并不会用到该类的equals方法,如Random类,虽然可以比较两个Random的实例,以判断两个实例是否可以产生相同的随机数,设计者认为这样的需求用到的场合很少,因而就没有重写equals方法。
3)父类已经实现了equals方法,并且父类实现方式和子类实现方式是一样的,如大部分的Set实现的equals方法使用AbstractSet类提供的equals方法,List实现则使用AbstractList,Map实现使用AbstractMap的。
4)一个private类或package-private类,我们自己可以确保我们不会使用到它们的equals方法。
同时书也提出一般只有值类型的类才需要实现equals方法,像Date、Integer、Order(作为bean来使用)等。
另外,我们在实现equals方法是也要遵循以下几个原则:
1)自反性(reflexive):x.equals(x)==true
2)对称性(symmetric):x.equals(y)==y.equals(x)
3)传递性(transitive):若x.equals(y)==true, y.equals(z)==true,则x.equals(z)==true。
4)一致性(consistent):多次调用x.equals(y)的结果应该是一样的。
5)对任何非null实例x,x.equals(null)==false。
根据这些特性,我们可以写出如下代码:
1 public class Customer implements Serializable {
2 private static final long serialVersionUID = 1L;
3
4 private String id;
5 private String name;
6 private String role;
7
8 @Override
9 public boolean equals(Object obj) {
10 if(obj == null) {
11 return false;
12 }
13
14 if(this == obj) {
15 return true;
16 }
17
18 if(!(obj instanceof Customer)) {
19 return false;
20 }
21
22 Customer other = (Customer)obj;
23 return (ObjectUtils.equals(id, other.id)
24 ObjectUtils.equals(name, other.name)
25 ObjectUtils.equals(role, other.role));
26 }
27
28 public String getId() {
29 return id;
30 }
31 public void setId(String id) {
32 this.id = id;
33 }
34 public String getName() {
35 return name;
36 }
37 public void setName(String name) {
38 this.name = name;
39 }
40 public String getRole() {
41 return role;
42 }
43 public void setRole(String role) {
44 this.role = role;
45 }
46 } 其中ObjectUtils类的代码如下:
1 public class ObjectUtils {
2
3 /**
4 * Compare whether the left and right is equals
5 * It has already considered the null case
6 *
7 * @param left
8 * @param right
9 * @return
10 */
11 public static boolean equals(Object left, Object right) {
12 if(left == null right == null) {
13 return true;
14 }
15 if(left == null right != null) {
16 return false;
17 }
18 return left.equals(right);
19 }
20 } 在《Effective Java》这本书中,貌似equals实现方法前面没有null、this的判断,因为instanceof可以解决null的问题,而super.equals()方法可以解决this问题,但是我还是喜欢把它们都分出来,这样写的更加明了一些。另外,事实上,这里的实现并没有遵循对称性的原则,因为如果A是B的子类,而这个equals方法在A类中,那么AInstance.equals(BInstance)==false,若B也实现了类似的equals方法,则BInstance.equals(AInstance)==true(当A没有新的比较字段时,或许这个时候A根本就不需要实现equals方法,如本文开头列出的第三条),这是因为AInstance instanceof BInstance == true,反之则为false。不过由于这种情况并不常见,所以就不去care了。:)
事实上,这里我之所以要记录这些代码,主要是因为有ObjectUtils类的存在。记得以前在学C#的时候,它的Object类提供了一个静态的Equals方法,我一直对这个方法的存在感到很疑问,直到这次自己写这个equals方法才弄明白,因为虽然在equals方法实现中,最后还要判断类字段是否equals,然后这些字段都有可能是null的,如果没有提供这个静态的equals方法,我们就需要自己来判断每个字段是否为null,然后才可以调用它的equals方法,这样就比较麻烦了,而Object.Equals方法正是对这种行为的封装,我们只要使用一个方法就可以安全的实现类成员的equals。这也是我加ObjectUtils类的意义所在。希望以后能有机会向这个ObjectUtils类填充更多的实用方法。:)
PS:如一楼所说在commons中的EqualsBuilder已经实现了相同的功能,而且代码更加完善,有兴趣的可以看看那里的代码,我这里只是对这次新的的记录,代码只是对当前我考虑的场景中使用,并没有考虑其他方面。另外,在《Effective Java》中也是建议equals和hashCode两个方法应该是同时实现的,一楼也有说可以用HashCodeBuider来实现,这个大家也不妨可以去看看里面的源码,最近时间不多,以后回来再看。。。。。。
“==”和equals 最大的区别 “==”和equals 最大的区别是 “==”是运算符,如果是基本数据类型,则比较存储的值;如果是引用数据类型,则比较所指向对象的地址值。 equals是Object的方法,比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。
详解“==”和equals的区别 “==”和equals 最大的区别是 “==”是运算符,如果是基本数据类型,则比较存储的值;如果是引用数据类型,则比较所指向对象的地址值。 equals是Object的方法,比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。
==与equals方法的区别 ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量的引用地址是否相等,只能用==操作符。
Object类的toString和Equals方法,以及Objects类的Equals方法 Object类 toString()方法 public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name =
hashCode和equals的区别(一) Hello,大家好,我是子悠,作为本周的小编我已经不想跟大家介绍自己了,这篇文章让我们跟随 Jay Pan( 哇,一位新作者哦)的步伐学习知识吧。下面是正文。
有面试官会问:你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?equals和hashCode都是Object对象中的非final方法,它们设计的目的就是被用来覆盖(override)的,所以在程序设计中还是经常需要处理这两个方法。下面我们一起来看一下,它们到底有什么区别,总结一波!
hashCode和equals的区别(二) Hello,大家好,我是子悠,作为本周的小编我已经不想跟大家介绍自己了,这篇文章让我们跟随 Jay Pan( 哇,一位新作者哦)的步伐学习知识吧。下面是正文。
有面试官会问:你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?equals和hashCode都是Object对象中的非final方法,它们设计的目的就是被用来覆盖(override)的,所以在程序设计中还是经常需要处理这两个方法。下面我们一起来看一下,它们到底有什么区别,总结一波!
equals 和 hashCode 到底有什么联系? 写在前面 Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和hashCode()都不是final方法,都可以被重写(overwrite)。
1)类的每个实例从本质上来说是唯一的,如Thread类的实例。
2)我们并不会用到该类的equals方法,如Random类,虽然可以比较两个Random的实例,以判断两个实例是否可以产生相同的随机数,设计者认为这样的需求用到的场合很少,因而就没有重写equals方法。
3)父类已经实现了equals方法,并且父类实现方式和子类实现方式是一样的,如大部分的Set实现的equals方法使用AbstractSet类提供的equals方法,List实现则使用AbstractList,Map实现使用AbstractMap的。
4)一个private类或package-private类,我们自己可以确保我们不会使用到它们的equals方法。
同时书也提出一般只有值类型的类才需要实现equals方法,像Date、Integer、Order(作为bean来使用)等。
另外,我们在实现equals方法是也要遵循以下几个原则:
1)自反性(reflexive):x.equals(x)==true
2)对称性(symmetric):x.equals(y)==y.equals(x)
3)传递性(transitive):若x.equals(y)==true, y.equals(z)==true,则x.equals(z)==true。
4)一致性(consistent):多次调用x.equals(y)的结果应该是一样的。
5)对任何非null实例x,x.equals(null)==false。
根据这些特性,我们可以写出如下代码:
1 public class Customer implements Serializable {
2 private static final long serialVersionUID = 1L;
3
4 private String id;
5 private String name;
6 private String role;
7
8 @Override
9 public boolean equals(Object obj) {
10 if(obj == null) {
11 return false;
12 }
13
14 if(this == obj) {
15 return true;
16 }
17
18 if(!(obj instanceof Customer)) {
19 return false;
20 }
21
22 Customer other = (Customer)obj;
23 return (ObjectUtils.equals(id, other.id)
24 ObjectUtils.equals(name, other.name)
25 ObjectUtils.equals(role, other.role));
26 }
27
28 public String getId() {
29 return id;
30 }
31 public void setId(String id) {
32 this.id = id;
33 }
34 public String getName() {
35 return name;
36 }
37 public void setName(String name) {
38 this.name = name;
39 }
40 public String getRole() {
41 return role;
42 }
43 public void setRole(String role) {
44 this.role = role;
45 }
46 } 其中ObjectUtils类的代码如下:
1 public class ObjectUtils {
2
3 /**
4 * Compare whether the left and right is equals
5 * It has already considered the null case
6 *
7 * @param left
8 * @param right
9 * @return
10 */
11 public static boolean equals(Object left, Object right) {
12 if(left == null right == null) {
13 return true;
14 }
15 if(left == null right != null) {
16 return false;
17 }
18 return left.equals(right);
19 }
20 } 在《Effective Java》这本书中,貌似equals实现方法前面没有null、this的判断,因为instanceof可以解决null的问题,而super.equals()方法可以解决this问题,但是我还是喜欢把它们都分出来,这样写的更加明了一些。另外,事实上,这里的实现并没有遵循对称性的原则,因为如果A是B的子类,而这个equals方法在A类中,那么AInstance.equals(BInstance)==false,若B也实现了类似的equals方法,则BInstance.equals(AInstance)==true(当A没有新的比较字段时,或许这个时候A根本就不需要实现equals方法,如本文开头列出的第三条),这是因为AInstance instanceof BInstance == true,反之则为false。不过由于这种情况并不常见,所以就不去care了。:)
事实上,这里我之所以要记录这些代码,主要是因为有ObjectUtils类的存在。记得以前在学C#的时候,它的Object类提供了一个静态的Equals方法,我一直对这个方法的存在感到很疑问,直到这次自己写这个equals方法才弄明白,因为虽然在equals方法实现中,最后还要判断类字段是否equals,然后这些字段都有可能是null的,如果没有提供这个静态的equals方法,我们就需要自己来判断每个字段是否为null,然后才可以调用它的equals方法,这样就比较麻烦了,而Object.Equals方法正是对这种行为的封装,我们只要使用一个方法就可以安全的实现类成员的equals。这也是我加ObjectUtils类的意义所在。希望以后能有机会向这个ObjectUtils类填充更多的实用方法。:)
PS:如一楼所说在commons中的EqualsBuilder已经实现了相同的功能,而且代码更加完善,有兴趣的可以看看那里的代码,我这里只是对这次新的的记录,代码只是对当前我考虑的场景中使用,并没有考虑其他方面。另外,在《Effective Java》中也是建议equals和hashCode两个方法应该是同时实现的,一楼也有说可以用HashCodeBuider来实现,这个大家也不妨可以去看看里面的源码,最近时间不多,以后回来再看。。。。。。
“==”和equals 最大的区别 “==”和equals 最大的区别是 “==”是运算符,如果是基本数据类型,则比较存储的值;如果是引用数据类型,则比较所指向对象的地址值。 equals是Object的方法,比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。
详解“==”和equals的区别 “==”和equals 最大的区别是 “==”是运算符,如果是基本数据类型,则比较存储的值;如果是引用数据类型,则比较所指向对象的地址值。 equals是Object的方法,比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。
==与equals方法的区别 ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量的引用地址是否相等,只能用==操作符。
Object类的toString和Equals方法,以及Objects类的Equals方法 Object类 toString()方法 public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name =
hashCode和equals的区别(一) Hello,大家好,我是子悠,作为本周的小编我已经不想跟大家介绍自己了,这篇文章让我们跟随 Jay Pan( 哇,一位新作者哦)的步伐学习知识吧。下面是正文。
有面试官会问:你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?equals和hashCode都是Object对象中的非final方法,它们设计的目的就是被用来覆盖(override)的,所以在程序设计中还是经常需要处理这两个方法。下面我们一起来看一下,它们到底有什么区别,总结一波!
hashCode和equals的区别(二) Hello,大家好,我是子悠,作为本周的小编我已经不想跟大家介绍自己了,这篇文章让我们跟随 Jay Pan( 哇,一位新作者哦)的步伐学习知识吧。下面是正文。
有面试官会问:你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?equals和hashCode都是Object对象中的非final方法,它们设计的目的就是被用来覆盖(override)的,所以在程序设计中还是经常需要处理这两个方法。下面我们一起来看一下,它们到底有什么区别,总结一波!
equals 和 hashCode 到底有什么联系? 写在前面 Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码。equals()和hashCode()都不是final方法,都可以被重写(overwrite)。
相关文章
- 设计模式——模板方法
- PHP 取302跳转后真实 URL 的两种方法
- java实现遍历树形菜单方法——OpenSessionView实现
- PHP操作Redis数据库常用方法
- Office 2013 Excel 打开文档很慢很慢的解决方法
- Java单链表的实现方法汇总整理
- java 中文乱码的解决方法
- python实现在目录中查找指定文件的方法
- Python实现全局变量的两个解决方法
- asp .net 为图片添加文字水印(内包含有加图片水印的方法) .
- Atitit io读取文件法 目录 1. 文件法1 1.1. 异步读取文件:1 1.2. 2.同步读取方法1 1.3. 二进制读文件:1 2. 读取api规范1 3. Atitit 按照
- Atitit 学习一项技术的方法总结 目录 1. 自己动手实现学习法1 2. 七步学习法 —— 如何高效学习一项技能1 3. 如何快速学习一项技能-十步学习法 - HugoLester - 博客
- Android 悬浮按钮 两种实现方法
- Python兼职私活接单方法大曝光,这七种方法你知道吗?教你月入三万!
- PHP面试题:php读取文件内容的几种方法和函数?
- 分布式光伏储能系统的优化配置方法(Matlab代码实现)
- 用于灵敏性分析的方法模型(Matlab代码实现)
- 【图像融合】用于图像融合方法、客观评估指标、弗里德曼(Friedman)统计检验及其事后检验研究(Matlab代码实现)
- 一种基于Harris-Laplace算法的角点检测方法(Matlab代码实现)
- 详解JS中 call 方法的实现
- 004-行为型-02-模板方法模式(Template Method)
- C#操作字符串方法 [万余字总结 · 详细]
- 在OpenCV里使用最简单方法实现二维码识别
- 对于方法的修饰词,子类方法要比父类的方法范围更加的宽泛
- python学习===实现定时发送,方法一
- Python实现跨文件全局变量的方法