1. 程式人生 > >"==" equals和hashCode的聯系和區別

"==" equals和hashCode的聯系和區別

obj 基類 答案 說明 static 創建 [] 地址轉換 基本

寫這篇文章的目的是自己徹底把三者搞清楚,也希望對你有所幫助。

1."=="運算符對與基本類型(int long float double boolean byte char short),比較的是他們的值。但是對於復合數據類型,比較的是他們的內存地址。

public class TestString {
    public static void main(String[] args){
        String s1="Hello";
        String s2="Hello";
        if(s1==s2){
            System.out.println(
"s1==s2"); }else{ System.out.println("s1!=s2"); } } }

運行結果 s1==s2

public class TestString {
    public static void main(String[] args){
        String s1=new String("Hello");
        String s2=new String("Hello");
        if(s1==s2){
            System.out.println(
"s1==s2"); }else{ System.out.println("s1!=s2"); } } }

運行結果 s1!=s2

分析:

當我們用String s1="Hello",再創建String s2="Hello"的時候,他會先去字符串緩沖池尋找相同的對象,因為我們之前創建了s1,s1被放在了字符串緩沖池中,

所以s2創建的時候,就找到了相同的值s1,s1和s2指向同一個對象。

當我們使用new的時候,就會新開辟一個內存地址,無論你怎麽比較都不會相等的。

public class TestString {
    
public static void main(String[] args){ String s1="Hello"; String s2=new String("Hello"); if(s1==s2){ System.out.println("s1==s2"); }else{ System.out.println("s1!=s2"); } } }

所以這個比較結果返回的也是s1!=s2,因為當我們用String s1="Hello"的時候,這個時候字符串緩沖池存在值Hello,但是接下來String s2=newString("Hello");他會怎麽辦呢,他會先去字符串緩沖池去找,如果池子沒有Hello,他會在字符串緩沖池創建一個字符串常量“Hello”,如果存在就不在字符串緩沖池中創建。然後會在堆中創建一個新的對象(無論字符串緩沖池有沒有都會執行)。所以說兩者內存地址不相等。

2.equals是Object基類中的一個方法,java中所有的類都是繼承Object 這個基類的。這個方法初始也是比較兩者的內存地址的,這是原始的Object中的equals方法源碼

 public boolean equals(Object obj) {
        return (this == obj);
    }

很明顯的看到方法裏面的==,說明比較的是內存地址。

但是有一些類中有自身的equals方法把原本的方法覆蓋掉了,就不再是比較兩者的內存地址了,而是比較的內容值,例如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;
    }

解釋:如果是對象類型直接比較內存地址,如果是String類型逐一比較內容值。

public class TestString {
    public static void main(String[] args){
        String s1="Hello";
        String s2=new String("Hello");
        if(s1.equals(s2)){
            System.out.println("s1==s2");
        }else{
            System.out.println("s1!=s2");
        }
    }
    
}

結果返回:s1==s2。

註意:那這樣的代碼又會返回什麽結果呢?

public class TestString {
    public static void main(String[] args){
        String s1="Hello";
        String s2=new String("Hello");
        s2=s2.intern();
        if(s1==s2){
            System.out.println("s1==s2");
        }else{
            System.out.println("s1!=s2");
        }
    }
    
}

返回結果:s1==s2。為什麽??答案:String#intern方法,這個方法是一個 native 的方法,“如果常量池中存在當前字符串, 就會直接返回當前字符串. 如果常量池中沒有此字符串, 會將此字符串放入常量池中後, 再返回”。

3.hashCode方法也是從Object類中繼承過來的,它是用來鑒定兩個對象是否相等,Object類中的的hashCode返回的是對象在內存中地址轉換成的一串int數值,如果沒有重寫hashCode方法,任何對象的hashCode都不會相等的。恰恰String的hashcode重寫了,你說氣人不。如果兩個對象equals相等,則hashCode必須相等,反之不成立。一般來說你重寫了equals,也要重寫HasCode。

"==" equals和hashCode的聯系和區別