關於java ==,equal() 以及 hashcode()
1.首先,'==' 大家都很熟悉就是比較地址,話不多說直接上程式碼 :
public class Demo {
public static void main(String[] args){
String s1 = "123";
String s2 = "123";
String s3 = new String("123");
System.out.println(s1==s2);//輸出 true
System.out.println(s3==s1);//輸出 false
}
}
上述程式碼,
首先簡單瞭解一下棧 和 常量池:
1>.棧:存放基本型別的
2>.常量池:存放字串常量和基本型別常量( public static final ,java存放字串用 public final 修飾的value陣列 )
s1,s2都是常量,其後面的 "123" 都被放在常量池中,其實在 s2 建立的時候,只是把已經在常量池中的 "123"賦值給了s1引用變數,這樣s1當然等於s2啦,因為兩者是一個東西,當然地址也相同。
至於s3為什麼不等於s1,那是因為,s3是new出來的,也就是說s3new出來的物件在堆中,s3這個引用變數在棧中,但是s1的物件在常量池中,這兩個當然地址不一樣啦!
2. equals方法
1>.首先上未經重寫的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; }
由上述程式碼不難看出,首先java 先比較兩個字串的地址是否相同,如果相同,那麼就直接返回true;
接下來,如果地址不相同,那麼分別獲取兩個字串對應的 char 陣列,進行遍歷比較每個字元是否相等,如果有一個不相等就返回false,否則就返回true。
注意:java已經將大部分類都重寫了equals方法!!! 只有少部分不需要用到equals的,才沒重寫。
3.hashcode() 方法
寫這個之前,我先說一下我之前遇到的一個小問題:
public class Demo {
public static void main(String[] args){
String a= null;
System.out.println(a.hashCode());
}
}
這段程式碼報錯
Exception in thread "main" java.lang.NullPointerException
at ttms.Demo.main(Demo.java:6)
之後我找到了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;
}
上述程式碼中會呼叫 value.length變數,value就是你的字串轉換成的字元陣列,那麼問題就簡單了,你傳進去的物件就是空的,那就肯定沒有length屬性啦,也就會報空指標異常。
補充一下:如果沒有重寫hashcode方法,那麼就返回的是物件的32位jvm記憶體地址。