阅读Object类的时候,首先引入眼帘的是:
private static native void registerNatives();
看到native关键字,我也是一通百度,也知道了native关键字是本地方法调用的关键字,自己也按照别人的博客做了一个demo,大致流程是先编译java文件,然后再对class文件用javah命令编译,然后书写我们要实现的本地cpp方法,我用的IDE是CodeBlocks,由于jvm是64位的,第一次生成的dll文件是32位dll文件,放到64位的jvm中提示不可用。
然后就去下载mingw64,在codebolcks上编译生成了dll文件,最后把dll文件放到java代码目录下,最后成功运行了一个java调用本地cpp方法的demo。
下面说一下Object类中的hashcode方法吧。
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by
* {@link java.util.HashMap}.
* <p>
* The general contract of {@code hashCode} is:
* <ul>
* <li>Whenever it is invoked on the same object more than once during
* an execution of a Java application, the {@code hashCode} method
* must consistently return the same integer, provided no information
* used in {@code equals} comparisons on the object is modified.
* This integer need not remain consistent from one execution of an
* application to another execution of the same application.
* <li>If two objects are equal according to the {@code equals(Object)}
* method, then calling the {@code hashCode} method on each of
* the two objects must produce the same integer result.
* <li>It is <em>not</em> required that if two objects are unequal
* according to the {@link java.lang.Object#equals(java.lang.Object)}
* method, then calling the {@code hashCode} method on each of the
* two objects must produce distinct integer results. However, the
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables.
* </ul>
* <p>
* As much as is reasonably practical, the hashCode method defined by
* class {@code Object} does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java™ programming language.)
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.System#identityHashCode
*/
public native int hashCode();
上面一大段话指出,hashCode()这个方法的受益对象包括那些集合类{@link java.util.HashMap}。
注释中标蓝的那段里说道,对于同一个程序(进程)里的某一个对象调用hashCode(),会返回相同的值,除非你改动了equals()方法。
言外之意也就是说,如果前面的条件不变,也就是在同一个程序里,对同一个对象多次调用hashCode(),如果你的equals()方法有改动,那么hashCode()方法的返回值也有可能不一样。这是为什么呢?
首先,这两个方法是有关系规则的。(假设有两个对象A和B)(PS:规则是定死的)
1、若A.equals(B)的返回值为true,那么A和B调用hashCode()方法的返回值一定相等。
2、即便A和B调用hashCode()方法的返回值相等,A.equals(B)的返回值也不一定为true。
举个栗子:我们都知道String对象在作比较的时候,我们都是用equals()方法,而不用==。因为equals()方法比较的是String对象字符串的内容,而==比较的是两个对象的地址,我们常常希望两个字符串内容相等,就判定它们是相等的,而不是引用地址相等。
那为什么equals()方法比较的就是字符串的内容呢?原因就是String源码里重写了equals()方法,它的隐含意义就是假设两个String对象str1和str2,只要它们存储的字符串内容相等,就可以认为这两个对象是相等的,那么它们的hashCode()方法势必也是根据字符串内容来进行计算的。
如果某一天,你修改了String的equals()方法(当然,String类是final修饰的,不可以被继承,不可以被修改,只是做个假设),你认为两个String对象只有在满足某一原则的情况下才可以被认为是相等的对象的时候,你就可以修改equals()方法,比如你认为str1="abcd",str2="dcba".也就是一个字符串是另一个字符串的倒叙输出的情况下,才可以认为str1和str2是相等的,那么这时候你必须去修改hashCode()方法。(PS:要满足以上两大原则。)
hashCode()方法就是根据对象去计算一个数值,假设你重写了equals()方法,你认为只有两个字符串满足str1="abcd",str2="dcba"的条件下,就认为str1和str调用equals()方法返回true。
这种情况下,出现一个str3="efgh",假设你的hashCode()方法是根据字符串是否符合字典序来进行返回值的,符合字典序或者字典逆序(如:"abcde","edcb")返回1,否则返回0,那么str3和str1的hashCode就相等了,但是它们调用equals()方法却不相等。
那么,这两个规则有什么好处呢?
其他很多博客里也提到了,一个应用场景就是hashSet,插入数据的时候,需要保证对象的唯一性,如果每插入一条记录都要调用equals()方法,那么当数据量比较大的时候,假设有1000000条数据的时候,是不是要调用1000000次equals()方法呢,有了hashCode()方法,我们只需要先调用hashCode()方法,看看有没有具有相同hashCode返回值的对象,只需要在这些对象上调用equals()方法就行了,理想情况下,这将大大提高效率。