來講說 Java中的「==」和「equals」


千里之行,始於足下。

在Java平常開發中,常常會碰見判斷兩個對象或者兩個值是否相等的狀況,而經常使用的判斷方法就是「==」和「equals」,今天就來講說這兩個的區別。緩存


「==」

主要用來判斷兩個對象的引用地址是否相同;
因此若是「==」兩邊的是兩個對象,那麼判斷的就是是否爲同一對象;
注1:若是對象的引用值是放在常量池中,例如字符串,相同字符串的引用地址相同,因此「abc"=="abc"的結果爲true。而經過new String()來聲明的,因爲引用地址不一樣,new String("abc") == new String("abc") 結果爲false。this

String A = "abc";  
String B = "abc";  
System.out.println(A == B); //true

String a = new String("abc");  
String b = new String("abc");  
System.out.println(a == b); //false
//ps:這裏String推薦使用equals來判斷是否相等,由於是舉例說明問題,因此強行用了==

注2:當判斷基本類型時,是直接比較引用指向堆裏面的具體值。code


「equals」

equals是Object類中的一個方法,其默認是使用「==」來判斷兩個對象是否相等:對象

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

因此若是一個對象沒有重寫equals方法,那麼對比都是引用地址。開發

equals要求知足幾個特性:字符串

  1. 自反性:對任意引用值X,x.equals(x)的返回值必定爲true. 
  2. 對稱性:對於任何引用值x,y,當且僅當y.equals(x)返回值爲true時,x.equals(y)的返回值必定爲true; 
  3. 傳遞性:若是x.equals(y)=true, y.equals(z)=true,則x.equals(z)=true 
  4. 一致性:若是參與比較的對象沒任何改變,則對象比較的結果也不該該有任何改變 
  5. 非空性:任何非空的引用值X,x.equals(null)的返回值必定爲false

而在平常使用中已經重寫了equals的經常使用類,有String,Integer等。源碼

String:

直接上源碼:hash

public boolean equals(Object anObject) {  
    if (this == anObject) {  //判斷引用地址是否相等
        return true;  
    }  
    if (anObject instanceof String) {  //傳入的參數是否爲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的equals時判斷兩個字符串的長度和每一位字符是否相等。循環

Integer:

仍是直接上源碼:引用

public boolean equals(Object obj) {  
    if (obj instanceof Integer) {  
        return value == ((Integer)obj).intValue();  //這裏的value是int類型的
    }  
    return false;  
}

Integer的equals是把兩個Integer對象轉化成基本類型int再經過==進行比較。
說到Integer,說一個遇到的坑:

Integer a = Integer.valueOf("127");  
Integer b = Integer.valueOf("127");  
Integer c = Integer.valueOf("128");  
Integer d = Integer.valueOf("128");  
  
System.out.println(a==b);  //true
System.out.println(c==d);  //false

這裏是由於,對於Integer的valueOf存在一個-128~127緩存:

public static Integer valueOf(int i) {  
    if (i >= IntegerCache.low && i <= IntegerCache.high)  //low=-128,high=127
        return IntegerCache.cache[i + (-IntegerCache.low)];  
    return new Integer(i);  
}

因此當值在緩存裏的時候,valueOf並無new 對象,從而致使裏a==b爲true。因此對於Integer大小的判斷,推薦使用equals。


總結

「==」和「equals」在沒有重寫Object裏equals方法的類裏,他們是同樣的。
而在平常的開發過程當中,類裏能夠重寫equals方法用來判斷兩個類是否相同。例如對於一個以手機號爲惟一標識的項目裏,能夠只判斷手機號就能確認兩個對象是否相等。
ps:再多說一句,通常重寫equals時也會重寫hashCode方法,至於爲何重寫hashCode方法,下次再說吧。

相關文章
相關標籤/搜索