废话不多说我们直接拿例子来说
1 Object a = "2"; 2 Object b = "2"; 3 Object obj1 = new Object(); 4 Object obj2 = new Object(); 5 System.out.println( a.hashCode() + " " + b.hashCode() );// 50 50 6 System.out.println( obj1.hashCode() + " " + obj2.hashCode() );//356573597 1735600054 7 String str1 = "a"; 8 String str2 = "a"; 9 String str3 = new String("a"); 10 String str4 = new String("a"); 11 System.out.println( str1.hashCode() + " " + str2.hashCode());//97 97 12 System.out.println( str3.hashCode() + " " + str4.hashCode());//97 97
我们得知道String类中的hashCode方法是重写了Object类的hashCode方法。hashCode方法返回一个哈希值。Object类中的hashCod方法是个本地方法我们没法看源码,但通过不同的渠道我们能得知这个哈希值是根据对象的内存地址计算出来的。而String类中的hashCode方法我们可以看到源码,so 我们来看下源码
1 public int hashCode() { 2 int h = hash; 3 if (h == 0 && value.length > 0) { 4 char val[] = value; 5 6 for (int i = 0; i < value.length; i++) { 7 h = 31 * h + val[i]; 8 } 9 hash = h; 10 } 11 return h; 12 }
我们从其中发现,String类的hashCode返回的哈希值,不是通过内存地址计算得到的,而是通过这个stirng值进行计算出来的,如果两个String值一样,这两个String的哈希一定相同。我们再来看下最开始的代码。因为 a和b地址相同,,所以hashCode的返回值也相同,而obj1和obj2是两个不同的对象,内存地址不一样,所以hashCode返回值不一样。而在str1,str2,str3,str4因为值都相等,所以hashCode返回的hash值都一样。
最后我们来总结下,为啥我们有时候比较一个类是不是相等,我们都得重写equals和hashCode方法。
1、如果都不重写。即使两个对象相等,euqals比较都是false,hashCode返回的值也都不一样,这样我们就没依据说这两个对象是相等的
2、如果只重写equals,不重写hashCode。那么两个相等的对象equals比较是true,但是他们的hashCode却不一样
3、如果只重写hashCode,不重写equals。重写后的hashCode是通过值来计算hash码,所以可能导致两个对象hash码一样,但是equals却不一样。
4、都重写。那么只要euqals比较是true,那么hash码一定相等。但是hash码相等,equals不一定相等。