其实很多时候看了博客,学习了相关知识,自己觉得自己懂了
但是往往又会忘记,因为不清楚真正的底层是如何实现的
今天,来给大家深入分析下
== 、 equals 以及 hashcode
给出第一个 case1
大家想一下结果是多少
// case1
String s1 = "a" + "b";
String s2 = new String(s1);
if(s1==s2) System.out.println("suuu");
if(s1.equals(s2)) System.out.println("jjjjjj");
3105
3105
jjjjjj
这里的 s1是 new出来的,他们的hashcode是相同的;
给出第一个结论
hashCode()方法常被设计用来提高性能,其两者的关系在于:
①若两个对象相等(equals),那么这两个对象一定有相同的哈希值(hashCode);
②若两个对象的哈希值相同,但这两个对象并不一定相等。
String s5 = "es";
String s6 = new String("es");
System.out.println("-----------");
System.out.println(s5.hashCode());
System.out.println(s6.hashCode());
System.out.println(s5==s6);
System.out.println(s5.equals(s6));
-----------
3246
3246
false
true
这里的 == 就是 判断出 包装类String的引用地址不同
System.out.println("-----------");
String s3 = "es";
String s4 = "es";
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());
System.out.println(s3==s4);
System.out.println(s3.equals(s4));
s3 = "123";
System.out.println("s3" + s3);
System.out.println("s4" + s4);
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());
System.out.println(s3==s4);
System.out.println(s3.equals(s4));
-----------
3246
3246
true
true
s3123
s4es
48690
3246
false
false
在这里,由于s3和s4同时定义,
于是jvm直接让两个引用指向了一个地址
这里地址相同,值相同,直接返回true
首先来看默认情况下 equals 比较一个有相同值的对象,代码如下:
class Cat {
public Cat(String name) { this.name = name; }
private String name; public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
class testDomeOne1 {
public static void main(String[] args) {
Cat c1 = new Cat("星期五");
Cat c2 = new Cat("星期五");
System.out.println(c1.equals(c2));
}
}
false
所以,重写toString方法吧
class Cat {
public Cat(String name) { this.name = name; }
private String name; public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
class testDomeOne1 {
public static void main(String[] args) {
Cat c1 = new Cat("星期五");
Cat c2 = new Cat("星期五");
System.out.println(c1.toString());
System.out.println(c2.toString());
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c1==c2);
System.out.println(c1.toString().equals(c2.toString()));
}
}
Cat{name='星期五'}
Cat{name='星期五'}
1846274136
1639705018
false
true
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
//这里还是判断的==
//但是下面增加了一个操作
//将String转为了char[]
/** public final class String
implements java.io.Serializable, Comparable, CharSequence {
private final char value[];
*/
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;
}
//instanceof 是 Java 的保留关键字。. 它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
没啥好讲的,就是这么简单
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;
}
class testDomeOne{
public static void main(String[] args) {
// case1
String s1 = "a" + "b";
String s2 = new String(s1);
if(s1==s2) System.out.println("suuu");
//==设计的目的就是为比较两个对象是否是同一个对象。
//比较对象的相等不仅要比较对象内容相等,还要比较对象引用地址是否相等。
if(s1.equals(s2)) System.out.println("jjjjjj");
//==比较的是两个对象是否是同一个对象,这并不能满足很多需求。
// 有时候当两个对象不==的时候,我们仍然会认为两者是“相等”的,
// 比如对于String对象,当两个对象的字符串序列是一致的,我们就认为他们是“相等”的。
// 对于这样的需求,需要equals()来实现。记得重写 toString
// case2
String s3 = "es";
String s4 = "es";
System.out.println("-----------");
System.out.println(s3.hashCode());
System.out.println(s4.hashCode());
System.out.println(s3==s4);
System.out.println(s3.equals(s4));
//hashCode()方法返回的是一个数值,称之为hashCode。hashCode()方法在Object类中的定义如下
//①若两个对象相等(equals),那么这两个对象一定有相同的哈希值(hashCode);②若两个对象的哈希值相同,但这两个对象并不一定相等。
// case3
String s5 = "es";
String s6 = new String("s5");
System.out.println("-----------");
System.out.println(s5.hashCode());
System.out.println(s6.hashCode());
System.out.println(s5==s6);
System.out.println(s5.equals(s6));
}
}