== 和 equals() 的區(qū)別
由于之后學(xué)習(xí)裝箱和拆箱的時(shí)候中會(huì)使用到 == 和 equals() 兩種方式來(lái)進(jìn)行兩個(gè)對(duì)象的對(duì)比,所以這里先看下在 Java 中 == 和 equals()的區(qū)別鹿霸。
==
下方代碼段分別對(duì)兩個(gè) int, float,String 類型的數(shù)據(jù)進(jìn)行了比較众眨。
int i1 = 333;
int i2 = 333;
System.out.println("i1 == i2 -> " + (i1 == i2));
float f1 = 0.3f;
float f2 = 0.3f;
System.out.println("f1 == f2 -> " + (f1 == f2));
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("str1 == str2 -> " + (str1 == str2));
--output
i1 == i2 -> true
f1 == f2 -> true
str1 == str2 -> false
結(jié)果可以看到 int 和 float 類型的數(shù)使用 == 進(jìn)行比較時(shí)結(jié)果為 true,而 String 類型比較的結(jié)果是 false.這是因?yàn)閕nt 和 float 都是基本數(shù)據(jù)類型,變量中存儲(chǔ)的就是其本身的值容诬,所以在使用 == 進(jìn)行比較的時(shí)候直接對(duì)比的就是值娩梨,所以結(jié)果是相等的。而 String 是非基本類型(或者描述為引用類型)览徒,變量存儲(chǔ)的是一個(gè)引用狈定,而 str1 和 str2 是通過(guò) new String() 方式生成的兩個(gè)不同的對(duì)象,其在內(nèi)存中的地址不同习蓬,所以使用 == 比較的結(jié)果是 false纽什。
而如下代碼段則展示了當(dāng)兩個(gè)變量引用同一個(gè)對(duì)象時(shí),其比較的結(jié)果躲叼。
String str1 = new String("hello");
String str2 = new String("hello");
String str3 = new String("no hello");
str1 = str3;
str2 = str3;
System.out.println("str1 == str2 ->" + (str1 == str2));
--output
str1 == str2 -> false
當(dāng)為 str1 和 str2 都賦值為 str3 時(shí)芦缰,str1 和 str2 存儲(chǔ)的都是 str3 值的地址,所以使用 == 對(duì)比結(jié)果是相同的枫慷。
綜上所述让蕾,== 是直接比較的值,但是因?yàn)榛绢愋妥兞恐苯哟鎯?chǔ)值或听,引用類型存儲(chǔ)地址的原因探孝。所以結(jié)果表現(xiàn)為基本類型使用 == 比較時(shí)直接比較值,而引用類型比較了地址誉裆,當(dāng)兩個(gè)引用類型的變量真實(shí)的值是相同的時(shí)候顿颅,比較結(jié)果也是 false。
equals()
equals() 是 Object 類提供的方法足丢,所以所有繼承自 Object 類的類都會(huì)擁有此方法元镀,其在 Object 類中的實(shí)現(xiàn)如下:
public boolean equals(Object obj) {
return (this == obj);
}
可以到在 Object 類中的實(shí)現(xiàn)是直接對(duì)比了兩個(gè)對(duì)象的引用。但是當(dāng)子類重寫(xiě)了 Object 方法時(shí)霎桅,就需要具體的看各自實(shí)現(xiàn)了,如 String 類和 Integer 類讨永。
String str1 = new String("hello");
String str2 = new String("hello");
System.out.println("str1.equals(str2) -> " + (str1.equals(str2)));
Integer i4 = 564;
Integer i5 = 564;
System.out.println("i4 == i5 ->" + (i4.equals(i5)));
--output
str1.equals(str2) -> true
i4.equals(i5) -> true
String 類的 equals() 實(shí)現(xiàn)如下:
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;
}
可以看到當(dāng)兩個(gè) String 對(duì)象的引用相同或值相同時(shí)都會(huì)返回 true,這樣就是上個(gè)例子中兩個(gè) String 比較返回 true 的原因滔驶。類似的,Integer 類的實(shí)現(xiàn)如下:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
也就是當(dāng)兩個(gè) Integer 類型的對(duì)象進(jìn)行比較的時(shí)候卿闹,會(huì)有拆箱操作揭糕,取出參數(shù)的 int 值進(jìn)行對(duì)比萝快。但是,這個(gè)地方需要注意著角,在 equals() 方法中有類型判斷揪漩,當(dāng)傳入的參數(shù)不是 Integer 類型是,會(huì)直接返回 false,這也可以理解為 equals() 方法不會(huì)進(jìn)行類型轉(zhuǎn)換吏口。
綜上所述奄容,equals() 方法默認(rèn)比較的是兩個(gè)對(duì)象的引用,但當(dāng)子類有重寫(xiě)行為時(shí)产徊,需要看具體實(shí)現(xiàn)昂勒,Integer,Long舟铜,Double 等包裝類型都重寫(xiě)了此方法戈盈,進(jìn)行值的比較。
根據(jù)以上結(jié)論谆刨,我們?cè)陂_(kāi)發(fā)中需要注意: 包裝類型間的相等判斷應(yīng)該用 equals塘娶,而不是 '=='.