==是物理相等

equals是逻辑相等

因为每个类的实例对象本质上都是唯一的 ,利用物理相等(==)是指一个实例只能相等于它自己。

利用逻辑相等是(equals)指 一个实例是否和另一个实例的某些关键域相等,从而来判断这两实例是否相等。

Object类的equals方法的实现:物理相等的话就逻辑相等。

什么时候不需要覆盖Object类的equals方法?

1.希望这个类的实例只能和自身相等,不覆盖equals方法,只继承Object类的equals方法。

我们比较这个类的实例对象是否相等,无论是使用 == 或者equals 实际上都是 进行物理相等的判断。

2.这个类的超类已经覆盖了Object类的equals方法,并且这个类继承超类的equals方法,对于它自身来说也是合适的,这时不覆盖equals方法。

例如:Set实现类都继承了AbstractSet类的equals方法,List实现类都继承了AbstractList类的equals方法,Map实现类都继承了AbstractMap类

的equals方法。

3.确定这个类的equals方法永远不会被调用时。

什么时候需要覆盖Object类的equals方法?

当一个类需要自己的特有的“逻辑相等”时,例如我们希望两个实例的某些关键域相等时,我们就认为它们两者是逻辑上相等的,调用equals方法就返回true。

如果不覆盖equals方法,继承Object类的equals方法,实际上进行的物理相等的判断,即一个实例只能和它自身相等。

例如:一些“值类”,如Integer,Date,String等,这些类我们在调用它们的equals方法时,希望只要两个实例的关键域相等,就返回true,而不是两个实例

是同一个实例时再返回true。而且这些类的equals方法必须被覆盖,从而在作为Map集合的key,或者Set集合的元素时出现符合预期的结果,因为它们的equals

方法会被调用来判断两个实例是否逻辑相等。

但是对于一些实例受控的类,如单例类,枚举类,这些类就不需要覆盖equals方法了。

正确覆盖equals方法,需要遵守它的通用约定:

1.自反性: x.equals(x) 必须返回true  。实例自身必然逻辑相等。

2.对称性: x.equals(y) 与 y.equals(x) 返回结果应该相同,同为true或者同为false。

3.传递性: x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)应该返回true。

4.一致性: 只要比较的实例对象的关键属性值没有改变 ,那么无论调用多少次equals方法返回的结果都应该相同,一致。

5.对于非null的x实例,x.equals(null) 永远返回false。

上面的五条约定,十分重要。有许多类,包括所有的集合类在内,都依赖于传递给它们的实例对象是否遵守了equals约定。

结合所有的约定需求,得到实现高质量equals方法的诀窍:

1.使用==操作符检查“参数对象的引用是否是调用对象”的相同引用。如果是,返回true。

2.使用instanceof操作符检查参数对象的类型是否正确。这里的类型正确,一般是指验证参数对象的类型是否是当前类。有些情况

也可以在当前类实现的接口的其他实现类,之间进行比较。

3.把参数对象转化为正确的类型。因为已经经过instanceof类型检查过了,类型转化可以确保成功。

4.对于该类中的每个“关键”域,检查参数对象中域是否与当前对象中对应的域相匹配。

如果上面的测试全部成功,就返回true,否则就返回false。

其中对于既不是float也不是double类型的基本类型域,可以直接使用==操作符进行比较,对于float类型的域,使用Float.compare方法,对于

double类型的域,使用Double.compare方法。对于引用类型的域,调用引用类型的equals方法进行比较。

当一个类的equals方法完成时,应该明确:它是否是对称的,传递的,一致的? 应该写测试代码去进行测试。

还要铭记一下告诫:

1.覆盖equals方法时总要覆盖hashCode方法。(第九条)

2.不要企图让equals方法太过智能。

3.不要把参数Object类型 换成任何其他类型。因为Object类提供的equals方法的参数类型就是Object,如果把参数Object类型换成其他类型,

就变成了equals方法的重载,而不是equals方法的重写。  所以可以添加@Override注解 来避免这种错误。

第八条:覆盖equals时请遵守通用约定的更多相关文章

  1. 第8条:覆盖equals时请遵守通用约定

    第8条:覆盖equals时请遵守通用约定 引言:尽管Object是一个具体类,但是设计它主要是为了拓展.它所有的非final方法(equals.hashCode.toString.clone和fina ...

  2. Item 8 覆盖equals时请遵守通用约定

    在覆盖equals方法的时候,你必须要遵守它的通用约定,不遵守,写出来的方法,会出现逻辑错误.下面是约定的内容:   equals方法实现了等价关系:   自反性.对于任何非null的引用值,x.eq ...

  3. 覆盖equals时请遵守通用约定

    Object类中非final修饰的方法有equals().hashCode().toString().finalize().clone()1.equals()方法不需要被覆盖的情况:1)实例化的对象只 ...

  4. 【Effective Java】4、覆盖equals时请遵守通用约定

    package cn.xf.cp.ch02.item8.transitivity; public class Point { private final int x; private final in ...

  5. 第10项:重写equals时请遵守通用约定

      重写equals方法看起来似乎很简单,但是有许多重写方式会导致错误,而且后果非常严重.最容易避免这类问题的办法就是不覆盖equals方法,在这种情况下,类的每个实例都只能与它自身相等.如果满足了以 ...

  6. 覆盖equals方法时请遵守通用约定

    覆盖equals方法时请遵守通用约定   覆盖equals方法看起来很简单,但是有许多覆盖方式会导致错误,并且后果很严重.最容易避免这种类问题的方法就是不覆盖equals方法,在这种情况下,类的每个实 ...

  7. EffectiveJava(8)覆盖equals是要遵守的约定

    覆盖equals是要遵守的约定 1.覆盖种类: -类的每个1实例本质上都是唯一的 -不关心类是否提供了"逻辑相等"的测试功能(Random测试是否能随机相同数字) -超类已经覆盖了 ...

  8. 重写equals时,遵守的规定

      0 正确的equals方法 public class MyClass { // 主要属性1 private int primaryAttr1; // 主要属性2 private int prima ...

  9. 第8条:覆盖equals时遵守通用约定

    如果不需要覆盖equals方法,那么就无需担心覆盖equals方法导致的错误. 什么时候不需要覆盖equals方法? 1.类的每个实例本质上是唯一的. 例如对于Thread,Object提供的equa ...

随机推荐

  1. [SCOI2007]降雨量

    ST表,再大力讨论一下(因为lower_bound和upper_bound,WA了一次) # include <bits/stdc++.h> # define RG register # ...

  2. Java的深拷贝和浅拷贝

    关于Java的深拷贝和浅拷贝,简单来说就是创建一个和已知对象一模一样的对象.可能日常编码过程中用的不多,但是这是一个面试经常会问的问题,而且了解深拷贝和浅拷贝的原理,对于Java中的所谓值传递或者引用 ...

  3. tp5.带标签的缓存 创建和清除 测试

    原文:http://www.upwqy.com/details/24.html 测试设置了标签的缓存的获取方式 和清除标签缓存. 有时候我们可能会对同类型的一些数据做统一缓存.和统一清除更新处理. 那 ...

  4. 关系型数据库工作原理-事务管理(二)(翻译自Coding-Geek文章)

    本文翻译自Coding-Geek文章:< How does a relational database work>. 原文链接:http://coding-geek.com/how-dat ...

  5. HttpSessionActivationListener序列化与反序列化

    一.序列化与反序列化 1.什么是序列化 把对象转化位字节序列的过程称为序列化(保存到硬盘,持久化) 把字节序列转化位对象的过程称为反序列化(存放于内存) 2.序列化的用途 把对象的字节序列永久保存到硬 ...

  6. NancyFX 第六章 视图引擎

    正如其他的Web工具包,Nancy也有视图的概念,用来描述在浏览器上看到的输出 视图的定义 你可能没有之前没有接触过"视图"的概念,或是仅仅是从其他工具包例如ASP.NET MVC ...

  7. NancyFX 第四章 Nancy快速上手 (使用Nancy模板)

    在我们进一步深入学习Nancy之前,我们先快速的了解下Visual Studio下的Nancy模板. 采用Nancy模板,创建一个Nancy项目就像我们创建MVC应用或winForm应用一样简单,只需 ...

  8. Python 3 中生成器函数yield表达式的使用

    生成器函数或生成器方法中包含了一个yield表达式.调用生成器函数时,会返回一个迭代子,值从迭代子中每次提取一个(通过调用其__next__()方法).每次调用__next__()时,生成器函数的yi ...

  9. 【django之分页器】

    一.什么是分页功能 二.Django的分页器(paginator) 语法: paginator = Paginator(book_list, 8) #8条一页print("count:&qu ...

  10. 笔记:Hibernate 查询缓存

    Hibernate 的一级缓存和二级缓存都是对实体进行缓存,他不会缓存普通属性,如果想对普通熟悉进行缓存,可以考虑使用查询缓存. 对于查询缓存来说,他缓存的Key就是查询所用的 HQL 或者 SQL ...