`
lc52520
  • 浏览: 369149 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

java中需要重写的hashcode() toString() 和equals()方法

    博客分类:
  • java
阅读更多

问题一:我们自定义类中的toString()、hashCode()和 equals(Object obj)均继承自Object,其中equals()方法是比较两对象的地址是否相同,hashCode()方法返回的是该对象本身的内存地址。但这个需 求不能满足我们的需求。如问题二。(JDK中其它类都已重写了上述方法,不作考虑)

    问题二:在我们往HashSet中添加自定义对象的时候(HashSet中不能添加相同的对象),HashSet会先将已存在的对象与欲添加的对象进行一 一对比,相同的对象不允许再添加。其比较规则为:如果两对象的hashCode()方法返回值不一样,肯定不是相同的对象,可添加;如果 hashCode()一样,则再判断equals()返回是否为真,不为真则肯定不是相同的对象,可添加,为真由证明两对象完全相同,不再添加到 HashSet中。那按Object()中的hashCode()方法,则只要内存不一样,则两对象的hashCode就不一样,则认为两对象不相同,可 往HashSet中添加,这违背了我们实际需求。

    结论:我们自定义类如果想往HashSet等集合中添加时,必须重写equals(Object obj)和hashCode()方法,使相同内容的对象其equals(Object obj)为真,返回的hashCode()一致。如下:

重写equals()方法
下面给出编写一个完美的equals方法的建议:

1) 显式参数命名为otherObject,稍后需要将它转换成另一个叫

做 other的变量。

2) 检测this与otherObject是否引用同一个对象:

        if (this == otherObject) return true;

        这条语句只是一个优化。实际上,这是一种经常采用的形

        式。因为计算这个等式要比一个一个地比较类中的域所付

        出的代价小得多。

3) 检测otherObject是否为null,如果为null,返回false。这项

      检测是很必要的。

                if (otherObject == null) return false;

      比较this与otherObject是否属于同一个类。如果equals的语

      义在每个子类中有所改变,就使用getClass检测:

              if (getClass() != otherObject.getClass()) return false;

      如果所有的子类都拥有统一的语义,就使用instanceof检测:

              if (! (otherObject instanceof ClassName)) retrun false;

4)将otherObject转换为相应的类类型变量:

        ClassName other = (ClassName)otherObject;

5) 现在开始对所有需要比较的域进行比较了。使用 == 比较

      基本类型域,使用equals比较对象域。如果所有的域都匹

      配,就返回ture;否则返回false。

              return field1 == other.field1

                        && field2.equals(other.field2)

                        && ……;

代码:

public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        Tree other = (Tree) obj;//Tree类        if (name == null) {            if (other.name != null)                return false;        } else if (!name.equals(other.name))            return false;        return true;    }        public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + ((name == null) ? 0 : name.hashCode());        return result;    }

********************************************************************************************************************

关于如何重写hashCode的方法

为什么要重写hashCode方法?

 

我们应该先了解java判断两个对象是否相等的规则。

 

在java的集合中,判断两个对象是否相等的规则是:


首先,判断两个对象的hashCode是否相等

如果不相等,认为两个对象也不相等
如果相等,则判断两个对象用equals运算是否相等
如果不相等,认为两个对象也不相等
如果相等,认为两个对象相等

 

我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率

 

如何重写hashCode方法呢?

 

你可以写

Java代码 复制代码
  1. public int hashCode(){   
  2.    return 42 ;   
  3. }  
public int hashCode(){
  return 42;
}

这是一种符合规则的写法,保证了两个equal 的object 拥有相同的hashCode

    但这种方法显然是不可取的

 

比较通用的做法是

返回一个result

 

Java代码 复制代码
  1. public int hashCode() {   
  2.    int result = 17 ;   //任意素数   
  3. result = 31 *result +c1; //c1,c2是什么看下文解释   
  4.    result = 31 *result +c2;   
  5.    return result;   
  6. }  
public int hashCode() {
  int result = 17;  //任意素数
 result = 31*result +c1; //c1,c2是什么看下文解释
  result = 31*result +c2;
  return result;
}

其中c1,c2是我们生成的你要计算在内的字段的代码,生成规则如下:

如果字段是boolean 计算为(f?1:0);

如果字段是byte,char,short,int则计算为 (int)f;

如果字段是long 计算为 (int)(f^(f>>32));

如果字段是float 计算为 Float.floatToLongBits(f);

如果字段是一个引用对象,那么直接调用对象的hashCode方法,如果需要判空,可以加上如果为空就返回0;
如果字段是一个数组则需要遍历所有元素,按上面几种方法计算;

 

当你写完后hashCode方法后问问自己

1、是否两个equal的实例,拥有相同的jhashCode

2、两个不同的实例,是否拥有相同的hashCode

写一个JUnit Test 测试一下

****************************************************************************************************************

01

一个重写equals ()和hashCode()方法的例子

下面是一个根据业务键实现equals ()与hashCode()的例子。实际中需要根据实际的需求,决定如何利用相关的业务键来组合以重写这两个方法。

 

Java代码 复制代码
  1. public class Cat   
  2. {   
  3.      private String name;   
  4.      private String birthday;   
  5.   
  6.      public Cat()   
  7.      {   
  8.      }   
  9.   
  10.      public void setName(String name)   
  11.      {   
  12.          this .name = name;   
  13.      }   
  14.   
  15.      public String getName()   
  16.      {   
  17.          return name;   
  18.      }   
  19.   
  20.      public void setBirthday(String birthday)   
  21.      {   
  22.          this .birthday = birthday;   
  23.      }   
  24.   
  25.      public String getBirthday()   
  26.      {   
  27.          return birthday;   
  28.      }   
  29.   
  30.         //重写 equals 方法   
  31.      public boolean equals (Object other)   
  32.      {   
  33.          if ( this == other)   
  34.          {   
  35.              //如果引用地址相同,即引用的是同一个对象,就返回true   
  36.              return true ;   
  37.          }   
  38.   
  39.              //如果other不是Cat类的实例,返回false   
  40.          if (!(other instanceOf Cat))   
  41.          {   
  42.              return false ;   
  43.          }   
  44.   
  45.          final Cat cat = (Cat)other;   
  46.              //name值不同,返回false   
  47.          if (!getName().equals (cat.getName())   
  48.              return false ;   
  49.              //birthday值不同,返回false   
  50.          if (!getBirthday().equals (cat.getBirthday()))   
  51.              return false ;   
  52.   
  53.          return true ;   
  54.      }   
  55.   
  56.         //重写hashCode()方法   
  57.      public int hashCode()   
  58.      {   
  59.          int result = getName().hashCode();   
  60.          result = 29 * result + getBirthday().hashCode();   
  61.          return result;   
  62.      }   
  63. }  
public class Cat 
{
 private String name;
 private String birthday;

 public Cat()
 {
 }

 public void setName(String name)
 {
  this.name = name;
 }

 public String getName()
 {
  return name;
 }

 public void setBirthday(String birthday)
 {
  this.birthday = birthday;
 }

 public String getBirthday()
 {
  return birthday;
 }

       //重写equals

方法
 public boolean equals

(Object other)
 {
  if(this == other)
  {
   //如果引用地址相同,即引用的是同一个对象,就返回true
   return true;
  }

            //如果other不是Cat类的实例,返回false
  if(!(other instanceOf Cat))
  {
   return false;
  }

  final Cat cat = (Cat)other;
            //name值不同,返回false
  if(!getName().equals

(cat.getName())
   return false;
            //birthday值不同,返回false
  if(!getBirthday().equals

(cat.getBirthday()))
   return false;

  return true;
 }

       //重写hashCode()方法
 public int hashCode()
 {
  int result = getName().hashCode();
  result = 29 * result + getBirthday().hashCode();
  return result;
 }
}

   重写父类方法的原则:可以重写方法的实现内容,成员的存取权限(只能扩大,不能缩小),或是成员的返回值类型(但此时子类的返回值类型必须是父类返回值类型的子类型)。

分享到:
评论

相关推荐

    equals,hashcode,toString

    在Java编程语言中,`equals()`, `hashCode()` 和 `toString()` 是三个非常重要的方法,它们主要用于对象的比较、哈希存储以及打印对象信息。这三个方法是Java对象的基础特性,对于理解和开发高质量的Java程序至关...

    java中重写equals()方法的同时要重写hashcode()方法(详解)

    在 Java 中,重写 equals() 方法和 hashCode() 方法是非常重要的,它们可以确保对象的比较和标识正确。如果我们违反了这两个方法的规则,那么可能会产生理解的不一致。因此,在编写 Java 代码时,需要严格遵守这两个...

    学习Object类——为什么要重写equeals和hashcode方法

    在 Java 编程语言中,Object 类是所有类的父类,但是在实际开发中,我们往往需要重写 Object 中的 equals 和 hashCode 方法,以便正确地比较对象的逻辑内容,而不是内存地址。下面我们将详细地解释为什么需要重写这...

    Java的Object类讲解案例代码 equals()、hashCode()、finalize()、clone()、wait()

    通过该案例代码,你可以学习如何在自己的类中正确重写equals()、hashCode()、toString()等方法,提高代码质量和可读性。 经验丰富的Java开发者:即使你已经有一定的Java开发经验,仍然值得深入了解Object类的使用。...

    JAVA_高级特性(hashCode,clone,比较器,Class反射,序列化)

    ### Java 高级特性详解 #### 一、`hashCode` ...正确地重写 `equals` 和 `hashCode` 方法、使用 `Comparator` 进行排序、利用反射机制和序列化技术,以及实现 `clone` 方法都是开发高质量 Java 应用程序的重要技能。

    javaee_tedu_day09.zip

    ATM系统 Clone方法 toString方法:表示返回对象的字符串表示形式 包名.类名@hashCode(内存地址) 打印对象时,默认调用 如果不是想使用object类,toString...如果equal返回true的话,hashCode相同,重写hashCode方法

    java课件 常用类与异常处理

    在Java中,`Object`类是所有类的父类,它提供了几个核心的方法,包括`equals()`, `hashCode()`, 和 `toString()`。 `equals()`方法用于比较两个对象是否相等。默认实现比较的是对象的引用,即两个对象是否指向内存...

    hashCode的作用

    在这个例子中,`Demo1`类重写了`equals`方法和`hashCode`方法。通过`equals`方法确保只有`value`相等时才认为两个对象相等;而`hashCode`方法则返回`id`的值。这样设计可以确保即使`id`不同但`value`相同的对象被视...

    Java toString的性能优化方案比较

    谁在关心toString的性能?没有人!除非当你有大量的数据在批量处理,使用...我们所钟爱的IDE们常常为我们生成equals/hashcode/toString这些方法,且我们通常不再去管它们。此外,这些IDE们提供了许多方式来生成我们自己

    Java Object 类高难度进阶版面试题集锦解析Java Object类高难度面试题及答案解析

    - 重写hashCode()时,如果两个对象根据equals()方法相等,它们的hashCode()方法必须返回相同的值。同时,不相等的对象返回不同的哈希码能提高哈希表的性能。 3. **toString() 方法**: - 默认的toString()方法...

    Java Object类认识

    本文将深入探讨`Object`类,以及其核心方法`equals()`与Java中的`==`操作符之间的差异。 `Object`类位于Java的核心库`java.lang`包中,它提供了基本的方法来支持对象的创建、比较和字符串表示。以下是`Object`类的...

    java中object类实例分析

    在实际编程中,我们经常需要重写Object类中的方法,例如equals和hashCode方法。这是因为这些方法的默认实现不适合我们的需求,我们需要根据自己的需求来重写这些方法。 例如,在上面的代码中,我们重写了equals和...

    Java实训教程 Java软件开发实战 Java类库 第1章 Object类 共29页.pptx

    因此,当重写`equals`方法时,通常也需要重写`hashCode`方法,确保两个`equals`结果为真的对象具有相同的哈希码。 #### 六、`toString`方法详解 - `toString`方法返回对象的字符串表示形式,默认情况下,`Object`...

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

    Object 类是 Java 中所有类的父类,它提供了几个重要的方法,例如 equals()、hashCode() 和 toString() 等。这些方法可以被子类重写,以满足子类的需求。 五、继承的注意事项 继承时需要注意以下几点: * 构造...

    JavaSE基础入门视频教程33天之(15) part1

    在这个阶段,主要讲解的是Java中对象的常用API,特别是关于`equals()`方法和`toString()`方法的使用,以及API的基本概念和`Object`类的概述。以下是这些知识点的详细解释: 1. **API概念**:API,全称为Application...

    java源码分析

    Object类中默认的equals()方法实现在Java中等同于“==”,它比较的是对象的引用地址是否相同。但许多类重写了equals()方法来比较对象的实际内容。 3. toString()方法在Object类中返回的是对象的类名加上“@”符号,...

    JAVA进阶-Java继承,多态,重写,修饰符以及super与this使用,Oject对象

    在Java中,所有的类都隐式或显式地继承自`Object`类,它提供了一些基本的方法,如`equals()`、`hashCode()`、`toString()`和`clone()`等。这些方法在处理对象比较、字符串化和复制等方面非常有用。 深入理解这些...

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

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

Global site tag (gtag.js) - Google Analytics