天天看点

toString、hashCode、equals的重写原因与重写示例

2009-02-19 16:03

    问题一:我们自定义类中的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()一致。如下:

public class Stu {

private String name;

private int age;

@Override

public boolean equals(Object obj) {

   if(!(obj instanceof Stu)){

    return false;

   }

   if(obj==null){

    return false;

   }

   Stu tmp=(Stu)obj;

   if(tmp.age!=this.age && !tmp.name.equals(this.name)){

    return false;

   }

   return true;

}

@Override

public int hashCode() {

   return this.age*this.name.hashCode();

}

public String getName() {

   return name;

}

public void setName(String name) {

   this.name = name;

}

public int getAge() {

   return age;

}

public void setAge(int age) {

   this.age = age;

}

}

测试类:

import java.util.HashSet;

public class Test {

public static void main(String[] args) {

   Stu s1=new Stu();

   s1.setAge(18);

   s1.setName("abc");

   Stu s2=new Stu();

   s2.setAge(18);

   s2.setName("abc");

   System.out.println(s1==s2);

   System.out.println(s1.equals(s2));

   HashSet set=new HashSet();

   set.add(s1);

   set.add(s2);

   System.out.println(set.size());

}

}

在上面的测试中两对象的年龄与姓名均一致,但其内存地址不一样。所以用"=="为假,用equals为真,返回的set.size()为1,即往HashSet中只能添加进一个对象。至于toString()方法较为简单,不多说了……