最近在看jvm优化的原理,不知不觉就看到引用和指针上的区别了,再然后就看了hash(散列)算法的实现思路,越看越不着边际,好吧,言归正传。
Java里面比较对象相等,有两种方式,一种是使用==号,另一种是使用equals方法。
==号:
判断两个对象的内存地址是否相等,相等则为同一个对象,不相等则不是,
对于基本类型数据,则只判断两个值是否相同。
equals方法:
Object类默认都实现了equals方法和hashcode方法,首先看一下equals方法的源码
object默认判断相等也是用的==号,即两个对象的内存地址是否相同。
有时候我们可能只需要两个对象的属性值相同,就认为这两个对象是同一个对象,或者我们只是比较对象的属性是否相同,而不需要判断内存地址是否相同,因为判断内存地址相同比消耗资源,这个时候我们就需要重写equals方法,比如String类默认就重写了equals方法,该方法默认就只判断内容是否相同。
首先判断内存地址是否相同,如果相同直接返回true,如果不相同,则判断内容是否相同。
hashcode方法:
Object默认实现了该方法,使用native修饰符,调用本地接口实现。
Java api对该方法的描述:
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
hashCode 的常规协定是:
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
一句话:返回的是在jvm中的伪地址,并不是真实的地址,但可以认为是真实的,因为不同的对象伪地址都会不同。
使用该方法的目的是在使用诸如Hashtable、HashSet、HashMap的时候,提搞HashMap存储对象的效率。
此时,equals方法和hashcode方法是相互独立的,并没有什么关系。
但在使用HashMap进行存储对象时,会判断对象的hash值和equals方法来决定是否已有对象存入HashMap中,看源码:
所以根据业务需要可能会重写Object的equals方法,但如果要把该对象放入HashMap、HashSet中,为了提高效率以及准确性,还需要重写Hashcode方法,因为Java规定:
equals方法相同,hashcode值必须相同,
equals方法不相同,hashcode值必须不相同,
这样才能确定该对象的唯一性。
toString方法:
Object默认实现是调用的Object的hashcode方法,可以看下源码,这里就不贴图了,System.out.print(obj)默认调用的是String的String.valueOf(obj)方法,而valueOf方法调用的又是该对象的toString方法,如果不重写toString方法的话,默认会调用Object的toString方法,所以个人感觉重写toString方法只是为了调试用的,比如打印对象的属性信息。现在一般都是debug了,感觉可重写,也可以不重写。
写的不好,欢迎指正。