关于在类中复写hashCode方法的返回值问题

来源:互联网 发布:java soap 客户端实例 编辑:程序博客网 时间:2024/06/06 02:36

如下程序:

class Person{

String name;

public Person(String name){

this.name = name;

}

}

public class Test{

public static void main(String args[]){

Person p1 = new Person("1");

Person p2 = new Person("2");

Person p3 = p1;

Person p4 = new Person("2");

System.out.println(“p1.hashCode(): ” + p1.hashCode());

System.out.println(“p2.hashCode(): ” + p2.hashCode());

System.out.println(“p3.hashCode(): ” + p3.hashCode());

System.out.println(“p4.hashCode(): ” + p4.hashCode());

}

}

此程序的Person类没有复写hashCode方法

如果分别输出四个对象的hashCode值 会发现p1和p3相同 虽然p2和p4的内容相同 但是hashCode值却不同

这是因为p2和p4分别new了一个对象 所以造成地址不同 导致hashCode值不同 而p1和p3却是引用的同一个在同一个地址的对象 所以他们的hashCode值相同

 

下程序复写了hashCode方法和equals方法

 

class Person{

String name;

public Person(String name){

this.name = name;

}

public int hashCode(){

return this.name * 15;

}

public boolean equals(Object obj){

if(this == obj)return true;

if(!(obj instanceof Person)) return false;

Person p1 = this;

Person p2 =(Person)obj;

if(p1.name.equals(p2.name)) return true;

else return false;

}

public String toString(){

return name;

}

}

public class Test{

public static void main(String args[]){

Person p1 = new Person("1");

Person p2 = new Person("2");

Person p3 = p1;

Person p4 = new Person("2");

System.out.println(“p1.hashCode(): ” + p1.hashCode());

System.out.println(“p2.hashCode(): ” + p2.hashCode());

System.out.println(“p3.hashCode(): ” + p3.hashCode());

System.out.println(“p4.hashCode(): ” + p4.hashCode());

System.out.println("p1.equals(p3) :" + p1.equals(p3));

System.out.println("p2.equals(p4) :" + p2.equals(p4));

System.out.println("p1.equals(p4) :" + p1.equals(p4));

System.out.println("p3.equals(p4) :" + p3.equals(p4));

}

}

此时在输出四个对象的hashCode值就发现与前一个有所不同了 这里p2和p4的内容是相同的 System.out.println("p2.equals(p4) :" + p2.equals(p4));输出的是true 同时输出的p2和p4的hashCode值也是相同的 但是前一个程序输出的却不一样 这是为什么 其实这里输出的hashCode只是一种equals方法和hashCode方法协议的结果 而这种协议就是当p2.equals(p4)为true时 p2.hashCode() == p4.hashCode()也为true 通俗的说就是当p2和p4的内容相同时 他们的hashCode值也应该相同 但是这个程序如果不复写hashCode方法时 对于输出p2和p4的hashCode值也和上一个程序的一样 所以应该同时复写equals方法hashCode方法 以便达成这种协议

 

但是这个程序的p2和p4的hashCode值真的就想结果一样吗 不要被结果所迷惑 因为这里已经复写了hashCode方法了 不管你复写hashCode方法的算法方式即如何计算在hashCode中返回的值 p2和p4的hashCode值还是相同的 这是因为系统会自动的将用equals比较的结果为true的两个对象的hashCode值设置为一样的 令人费解的是 明明p2和p4的地址不同 那输出hashCode值为什么相同 只要记住 这里输出的p2和p4的hashCode值相同只是个虚拟的结果 是为了与equals方法相对应而已 是为了达成这个协议 如果不复写hashCode方法就不会出现这种情况  

 

有一个方法可以消除以上的迷茫:

public static int identityHashCode(Object x) 这是System类中的一个静态方法 起作用是:

返回给定对象的哈希码,该代码与默认的方法 hashCode() 返回的代码一样,无论给定对象的类是否重写 hashCode()。null 引用的哈希码为 0。

意思是说 无论你有没有复写hashCode方法 他的返回结果将是根据地址算出来的不变的int值 这里如果分别输出p2和p4的identityHashCode就会发现他们的值不同 如果在类中复写了hashCode方法 但是想要得到原始的hashCode值就应该调用System.identityHashCode(obj)方法

 

 

以上是个人总结 不排除错误 慎重

原创粉丝点击