参考自:
https://www.cnblogs.com/baotong-9396/p/7182906.html
http://www.cnblogs.com/panxuejun/p/5866869.html
如题
作为一个写惯了js的人来说,初次接触java会有各种不习惯。其中有一个比较显著地不能理解的现象就是在java中比较两个String值是否相等居然用equals()
而不是==
。貌似在js中,比较值相等一个==
就解决了,多么舒服。为什么java不行呢?
首先,写过js的都知道,js支持=
,==
以及===
三种等号,第一个代表赋值,第二个用来表示值是否相等,而第三个用来判断是否是完全相等的对象。但是!java里并没有===
比较符。
在js中,
===
可以判断两个对象是否完全相等,不仅比较值也比较了内存地址,类型等,而java中的==
其实和js中的===
一样。这种比较是针对两个String类型的变量的引用,也就是说如果两个String类型的变量,它们所引用同一个String对象(即指向同一块内存堆),则==
比较的结果是true
。
而当两个String对象通过equals()
方法来进行比较时,其实就是对String对象所封装的字符串内容进行比较,也就是说如果两个String对象所封装的字符串内容相同(包括大小写相同),则equals()
方法将返回true
。(String对象继承自Object,并且对equals()方法进行了重写。)
示例一:
示例二:
为啥示例一和示例二打印输出不一样呢?
很简单的,示例一通过new
关键字在内存里开辟了两处空间,使用==
比较当然是false
了。而示例二直接将String作为基本类型使用,因此虚拟机不会为它们分配新的内存空间,而是到String缓冲池中来寻找。
示例三:
这个也很好理解,将s1
赋值给s2
,其实就是让s2
与s1
引用同一个对象。
在见识了以上三种应用示例后,我们是不是有必要去看看equals()
方法的源码实现,以方便我们更好的理解?
String.class
- 以示例一为例,通过
new
关键字分别调用了public String(String original)
构造函数,通过该构造函数对value
和hash
进行赋值。 - 随后先判断
s1
,s2
是不是引用同一个对象,是的话返回true
不是继续下一步。 - 通过判断用来比较的第二个对象是不是String类型,之后通过强转进一步确保。
- 用一个变量
n
来保存第一个String对象值的长度,然后先比较这两个String对象值长度是否相等,相等继续否则返回false
。 - 将这两个String对象的值分别保存进两个
char
类型的数组,通过循环对比相同下标对应的字符是否相等,存在一个不等就结束并返回false
,如果全部都一一对应相等,那么就返回true
。
对equals做个总结
以上主要对equals()
的源码进行了分析,仔细观察跟compareTo()
里面的源码很大程度上相似,感兴趣的可以去看看哦。
延伸
String.class里面的equals()
重写覆盖自顶级对象Object
,Object
里面的equals()
源码很简单,直接用==
判断两个对象是不是相同。
如果两个Object类型的对象使用
equals()
并返回true,说明它们是相同的,包括在内存中的存储地址,所以它们的hashcode
也相同!!!
思考一下:如果两个非Object类型的对象(例如本文中的String)使用equals()
并返回true,那么它们的hashcode
是否相同呢?
示例四:
通过上述示例可以看到,s1
与s2
其实是对两个不同的对象的引用,它们仅仅是值相同罢了,但是它们却拥有着相同的hashcode
!!!
那么,是不是equals
相同hashcode
一定相同呢?
先给出结论:
- 如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。
- 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
为什么会做出上面的判断呢?不妨看看源码实现吧。依然以String.class为例:
研读源码思考:
主要关注
hashCode()
内部实现,我们发现它最终返回的是h
,而h
其实就是通过value
值循环遍历累加得到的。那么如果两个对象调用equals
相等,不就意味着它们的值相等吗?hashCode()
也是通过值来计算的,这样能不等吗?
那么为什么说hashcode
相等,对象未必相同呢?
我个人理解,虽然hashCode()
依赖于value
值,但是它并没有逐一去比较每个下标对应的值是否相同,仅仅是判断累加值,那么假设两个对象的value
值不同但是累加值却相同不就造成了hashcode
相同吗?可事实上这两对象并不相同!