一.原因
1.String类重写了equals方法,在原有Object的equals逻辑的基础上新增了如果字符串的value值相同也为true。
2.若不重写hashCode方法,会存在两个字符串对象equals方法结果为true,hashCode方法为false。
3.如果两个对象的hashCode不同,则这两个对象肯定不同。如果两个对象equals相等,hashCode也有可能不同。
4.hashCode方法的好处在于返回值都是数值,比较起来简单,hashCode不同则没有必要去比较equals是否相等,能提高比较的效率。
5.在散列集合中,例如HashMap中,通过大量计算key的hash来计算当前元素的hash在数组所处的位置,用的就是hashCode。只有当hashCode相同时,才会放在同一个数组的位置,再去比较同个位置上的链表或树节点中的元素是否equals,这样先比较一遍hashcode,缩小equals的范围,提高效率。
6.如果String的equals相同,hashCode的不同,这样在HashMap中不同的数组位置可能会存在相同的元素,这是不对的。
二.说明
1.什么是==
1.在Java中,基本数据类型 == 比较的是值;对象类型 == 比较的是对象的地址。
2.String类是使用频率非常高的一种对象类型,JVM为了提升性能和减少开销,避免字符串的重复创建,因此维护了一块特殊的内存空间,即字符串常量池。
3.当需要使用字符串时,先去字符串常量池查看该字符串是否已经存在,如果存在,则可直接使用;如果不存在,则初始化,并将该字符串放入到字符串常量池中。
4.在JDK1.6及之前版本,字符串常量池在方法区中;在JDK1.7及以后版本,字符串常量池在堆中。
5.==判断的是对象内存的地址,因此相同的字符串String str = "abc";String str2 = "abc";在字符串常量池中会返回同样的地址,则返回true。
6.字符串String str = "abc";字符串对象String str2 = new String("abc");字符串对象str2的地址在堆空间,字符串str的地址在字符串常量池,因此两者不相等。
7.字符串对象String str = new String("abc"); 字符串对象String str2 = new String("abc"); str和str2均在堆空间,是2个对象,地址一定是不同的,所以两者不相等。
2.String的equals方法
1.如果内存相同则直接返回true
2.如果是String类型,则先比较value的长度,不同则false,相同则挨个比较字符是否相同,有一个不相同则false
三.源码
1.Object类的equals方法
// Object类的equals方法源码
public boolean equals(Object obj) {
return (this == obj);
}
2.String类中的equals方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
3.String类的hashCode方法
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/92326.html