`
xinklabi
  • 浏览: 1591975 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
文章分类
社区版块
存档分类
最新评论

重写hashCode()和equals()方法的注意事项

    博客分类:
  • Java
 
阅读更多

覆盖equals时需要遵守的通用约定
覆盖equals方法看起来似乎很简单,但是如果覆盖不当会导致错误,并且后果相当严重。《Effective Java》一书中提到“最容易避免这类问题的办法就是不覆盖equals方法”,这句话貌似很搞笑,其实想想也不无道理,其实在这种情况下,类的每个实例都只与它自身相等。如果满足了以下任何一个条件,这就正是所期望的结果:

    • 类的每个实例本质上都是唯一的。对于代表活动实体而不是值的类来说却是如此,例如Thread。Object提供的equals实现对于这些类来说正是正确的行为。
    • 不关心类是否提供了“逻辑相等”的测试功能。假如Random覆盖了equals,以检查两个Random实例是否产生相同的随机数序列,但是设计者并不认为客户需要或者期望这样的功能。在这样的情况下,从Object继承得到的equals实现已经足够了。
    • 超类已经覆盖了equals,从超类继承过来的行为对于子类也是合适的。大多数的Set实现都从AbstractSet继承equals实现,List实现从AbstractList继承equals实现,Map实现从AbstractMap继承equals实现。
    • 类是私有的或者是包级私有的,可以确定它的equals方法永远不会被调用。在这种情况下,无疑是应该覆盖equals方法的,以防止它被意外调用:
    • @Override

 

      public boolean equals(Object o){

 

      throw new AssertionError(); //Method is never called

 

      }

 



在覆盖equals方法的时候,你必须要遵守它的通用约定。下面是约定的内容,来自Object的规范[JavaSE6]

  • 自反性。对于任何非null的引用值x,x.equals(x)必须返回true。
  • 对称性。对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true
  • 传递性。对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。
  • 一致性。对于任何非null的引用值x和y,只要equals的比较操作在对象中所用的信息没有被修改,多次调用该x.equals(y)就会一直地返回true,或者一致地返回false。
  • 对于任何非null的引用值x,x.equals(null)必须返回false。


结合以上要求,得出了以下实现高质量equals方法的诀窍:
1.使用==符号检查“参数是否为这个对象的引用”。如果是,则返回true。这只不过是一种性能优化,如果比较操作有可能很昂贵,就值得这么做。
2.使用instanceof操作符检查“参数是否为正确的类型”。如果不是,则返回false。一般来说,所谓“正确的类型”是指equals方法所在的那个类。
3.把参数转换成正确的类型。因为转换之前进行过instanceof测试,所以确保会成功。
4.对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。如果这些测试全部成功,则返回true;否则返回false。
5.当编写完成了equals方法之后,检查“对称性”、“传递性”、“一致性”。
注意:

  • 覆盖equals时总要覆盖hashCode 《Effective Java》作者说的
  • 不要企图让equals方法过于只能。
  • 不要将equals声明中的Object对象替换为其他的类型(因为这样我们并没有覆盖Object中的equals方法哦)



覆盖equals时总要覆盖hashCode
一个很常见的错误根源在于没有覆盖hashCode方法。在每个覆盖了equals方法的类中,也必须覆盖hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap、HashSet和Hashtable。

  • 在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。
  • 如果两个对象根据equals()方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。
  • 如果两个对象根据equals()方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生相同的整数结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。
分享到:
评论

相关推荐

    重写equals和hashcode方法_equals_重写equals和hashcode方法_

    以下是对`equals()` 和 `hashCode()` 方法的详细解释及其重写的重要性。 **1. equals() 方法** `equals()` 方法用于比较两个对象是否相等。默认情况下,`equals()` 检查两个对象是否是同一个对象(即内存地址是否...

    【面试】hashCode与equals两者之间的关系 / == 和equals / 为什么要重写equals方法 / 重写equals /hashcode方法 / 为什么要重写hashCode方法

    7、**重写hashCode()方法的注意事项**: 重写`hashCode()`时,应确保它与`equals()`方法的逻辑一致。通常,`hashCode()`应该基于对象的那些参与`equals()`比较的属性来计算。如果两个对象`equals()`相等,它们的`...

    equals方法的重写.docx

    1. **`equals`方法和`hashCode`方法应保持一致性**:如果两个对象根据`equals`方法是相等的,那么它们的`hashCode`也应该是相等的。这是因为某些集合框架(如`HashMap`)会使用`hashCode`来定位元素,而使用`equals`...

    深入 HashCode 方法~

    ### 深入理解 HashCode 方法 #### 一、HashCode 的基本概念与作用 在 Java 编程语言中,`HashCode` 是一个非常重要且基础的概念。...对于自定义类来说,正确地重写 `hashCode()` 和 `equals()` 方法是非常必要的。

    hashcode使用方法

    #### 重写hashCode的注意事项 1. **一致性**:在一个执行期间,只要对象的状态没有改变,其 `hashCode` 方法应该始终返回相同的值。 2. **性能考虑**:应尽可能减少碰撞(不同的对象具有相同的哈希码),同时保持...

    hashcode与eqault比较

    // 重写hashCode方法 @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; } } ``` 在这个例子中: - `equals`方法检查两个`...

    如何正确实现Java中的HashCode共6页.pdf.z

    注意事项** - 不要让`hashCode()`返回`0`或负数,因为这可能导致哈希表性能下降。 - 当对象的状态改变导致`equals()`返回`false`时,`hashCode()`也应该返回不同的值,以反映这种变化。 - 如果类的实例不会与其他...

    day004 面向对象3-继承、抽象和方法的重写.doc

    面向对象编程之继承、抽象和方法重写 面向对象编程是一种编程范式,强调模块化、抽象化和继承性。在 Java 中,继承、抽象和方法重写是面向对象编程的三大要素。本文将对这三者进行详细的解释和说明。 一、继承...

    Java常见笔试、面试系列深度剖析第六讲

    当重写equals()方法时,务必同时重写hashCode()方法,以保持equals()和hashCode()的一致性。此外,要遵循以下原则: 1. 自反性:对于任何非null引用x,x.equals(x)应返回true。 2. 对称性:如果x.equals(y)返回true...

    Java中Equals使用方法汇总

    本文将深入探讨`equals`方法的使用方法、重写注意事项以及与`hashCode`方法的关系。 ### Q1. 何时应该重写`equals`方法? 在需要比较对象的值而不是引用时,应重写`equals`方法。默认情况下,`equals`方法使用`==`...

    学习Java时自己整理的知识点 4

    - 如果需要比较两个对象的内容是否相同,最好明确地重写`equals`方法,并且遵循一致性原则(即`equals`方法应该与`hashCode`方法配合使用,以确保正确的行为)。 通过上述分析,我们可以清楚地看到`equals`方法与...

    java面试重点总结

    - 获取类的所有属性和方法。 - 调用类的方法或设置/获取属性的值。 - **实现方式**: - 使用`Class`类的`forName()`方法。 - 对象的`getClass()`方法。 - 使用`.class`的方式获取类的`Class`对象。 - **注意...

    基础Java面试题,适合校招的面试笔试环节.doc

    #### 四、重写`equals`方法的注意事项 - **问题**: 重写`equals`方法时应该注意什么? - **解答**: 当重写`equals`方法时,通常还需要重写`hashCode`方法来确保一致性。这是因为根据`Object`类中的`equals`方法规范...

    经典的Java基础面试题.docx

    3. **重写 equals 方法需要注意的事项**: - 当重写 `equals` 方法时,通常需要同时重写 `hashCode` 方法。这是因为在Java中,`equals` 方法用于比较两个对象的内容是否相等,而 `hashCode` 方法用于确定对象在哈希...

    在Java(Android)中equals()与==

    - 当自定义类时,若要实现基于内容的相等性,应同时重写`equals()`和`hashCode()`方法,以遵守`equals()`和`hashCode()`的约定。 6. 示例: ```java class MyClass { int value; @Override public boolean ...

    java-object类

    2. **提供通用方法**:`Object` 类定义了一些非常重要的方法,如 `equals()`、`hashCode()` 和 `toString()`,这些方法在几乎所有 Java 类中都有应用。 3. **支持多态性**:通过继承 `Object` 类,Java 支持多态性,...

    经典Java基础面试题集锦

    3. **重写equals方法的注意事项** - **equals与hashCode的关系**:当重写`equals`方法时,通常还需要重写`hashCode`方法以确保一致性。这是因为在Java中,如果两个对象根据`equals`方法定义的规则相等,则它们的`...

    JAVA中常用类的常用方法.docx

    - 当两个对象通过 `equals()` 方法比较相等时,它们的 `hashCode()` 必须返回相同的值。 - 如果两个对象的 `hashCode()` 相同,并不一定意味着它们相等。 - **notify()方法** - **功能**:唤醒在此对象监视器上...

    Java面向对象(进阶)- Object类的详细概述

    在Java编程语言中,面向对象是其核心特性之一。Object类是所有Java类的根父类,无论何时我们创建一个新的类,除非明确指定其他...在实际项目中,合理地重写`equals()`和`toString()`方法对于调试和日志记录尤其有用。

    hashcode2021:源HashCode 2021

    - 探讨`hashCode()`在并发编程中的应用和注意事项 - Java集合框架中哈希码的使用 - 跟踪调试哈希冲突并解决实际问题 通过参加源HashCode 2021活动或学习相关资料,开发者可以提升对Java哈希码的理解,优化自己的...

Global site tag (gtag.js) - Google Analytics