覆盖equals时请遵照通用约定(8)

一、覆盖equals方法需谨慎,可能会致使严重后果java

  • 最容易避免的方式就是,不去覆盖

二、覆盖equals 方法指望你知足:sql

(1)类的每一个实例本质上都是惟一的数组

  • 表明活动实体而不是值得类确实如此
  • Object 的equals 本质调用的是 ==
  • 对于像String 类就是作值判断,和这里要求的惟一不是一种状况

(2)不关心类是否提供了”逻辑相等“的测试功能ide

  • 在类的每一个实例都与自身相等状况下,从Object继承已经足够了

(3)超类已经覆盖了equals 方法,从超类继承的equals方法对于子类也是合适的性能

  • Set实现都从AbstractSet 继承equals 实现,Map、List 也是

(4)类是私有的 或包级私有的 能够保证equals 方法永远不会被调用测试

  • 未声明(包级私有)、 public、protected、private
  • 类的访问权限:

  • 要咱们用代码来保证,以防其被之外调用

三、何时须要覆盖equals 方法:优化

  • 类具备本身独有的逻辑相等概念(不一样于对象等同概念)
  • 父类又没有实现指望的 equals 行为
  • 一般指 ”值类“ 如String、Integer、Date等
  • 覆盖equals 方法,还须要使类的实例能够作map的key ,集合(set)的相关要求
  • 上述map的key 要求不相等,集合(set)不能有重复项:都是equals判断的
  • 实际上,上述先用hashcode判断,而后再equals 比较,提升效率

四、实例受控<1条>确保每一个值最多存在一个对象的状况,不用覆盖.net

  • 好比:枚举类型(逻辑相等等同于对象等同)

五、覆盖equals 方法,遵照通用约定:code

(1)自反性:任何非null 值,x.equals(x) 必须返回true对象

(2)对称性:任何非null 值,x.equals(y)==true,则必须知足y.equals(x)==true

  • 以下红框所示,该类实例和String 实例比较时
  • caseIns.equals(str)==true,可是 str.equals(caseIns)==false

(3)传递性:任何非null 值,x.equals(y)==true,x.equals(z)==true,则必须知足x.equals(y)==true

  • 咱们没法扩展可实例化类的同时,既增长组件,又保留equals 方法的约定

ColorPoint 继承自Point ,多了一个color 属性

覆盖equals 方法1:

  • 该方法问题在于,没法比较 p.equals(cp)==true, cp.equals(p)==false 没有实现传递性

覆盖equals 方法2:

  • instanceof具备传递性(实例 的类、父类、实现接口 都知足)
  • 实现了对称性,没有实现传递性

好比:

  • p1.equals(p2)==true,p2.equals(p3)==true, 可是:p1.equals(p3)==false

这里可使用组合的方式知足上述需求:

  • java.sql.Timestamp 扩展了java.util.Date 增长了域,不知足equals 约定,是很差的案例

可是,咱们能够在抽象类的子类中添加新的组件、而且不违反equals 约定

(4)一致性;任何非null 值,只要equals 比较所用信息没变,屡次调用 都能获得 x.equals(y)==true

  • equals 方法永远不要依赖不可靠资源
  • java.net.URL的equals 方法依赖于主机IP地址的比较,IP地址是不靠谱资源,由于IP地址会变

(5)非空性:对于任何非null 值,必有 x.equals(null)==false

  • 下述 判空是没必要要的

  • 判空没必要要缘由以下,即类型判断的存在
  • 若是 o 是空,instanceof 返回的都是false,因此不须要单独判空

有许多类,包括全部集合类,都依赖于传递给他们的equals 方法是否听从约定

六、高质量equals 方法实现诀窍:

(1)使用== 检查 "参数是否为这个对象的引用"

  • 仅仅是性能上的一种优化

(2)使用instanceof 检查 ”参数是否为正确的类型“

  • 也能够是接口

(3)把参数转换成正确的类型

(4)检查该类中的每一个”关键“域,检查参数中的域是否与该对象中对应的域相匹配

  • 若是是接口,必须经过接口方法访问每个域
  • 类的话,根据可访问性访问
  • 对于非(float、double)浮点的基本类型,可采用== 比较
  • 对于浮点数,可采用Float.compare、Double.compare比较
  • 浮点数特殊处理是必要的,由于存在Float.NaN、-0.0f等特殊常量(Double相似)
  • 数组域,对每一个元素比较;或者采用Arrays.equals方法比较
  • 有些引用域null 是合法的,采用下述比较:

  • 相同的对象引用,下述方法更快:

  • 域的比较比等同比较复杂得多,可保存”范式“ 以尽可能使用低成本精确比较

域的比较顺序也会影响性能

  • 优先比较开销最低的域、最可能不一致的域,同时知足两者

(5)完成equals 方法,再三确认是否 对称、一致、传递

  • 还有 自反性、非空性,这俩通常自动知足
  • 覆盖equals  时,总要覆盖hashcode<9条>
  • 不要企图让equals 过于智能 不要过分准求各类等价关系

如:File 类的指向同一个文件的各类符号连接相等,File 没有那么作

  • 不要将equals 参数中的Object 替换成其余类型
  • 以下所述,这样并无覆盖Object的equals 方法,仅仅重载了equals 方法
  • 这样在某些时候提高性能,但复杂度加大,得不偿失

  • 使用@Override 编译器会告诉你问题

相关文章
相关标签/搜索