NO.2 equals與==的三生三世 | Java敲黑板系列

開場白

在Java家族裏,“equals”與“==”是最容易讓老鐵混淆、分不清楚的一對表兄弟。爲了便於大家提升對他們的辨識度,老鐵專門對他們進行了採訪,以下是採訪實錄。
老鐵 :應廣大老鐵們要求,今天我們非常幸會請來了“equals”和“==”兩位Java家族成員到“Java敲黑板系列”演播廳,歡迎兩位!
equals :大家好,我是equals,感謝大家收看今天的“敲黑板系列”!
== :大家好,我是==,感謝大家收看今天的“敲黑板系列”!
老鐵 :兩位經常活躍在各大舞臺,都是代碼資深人士,也給大家留下了很深刻的印象。但是,大家很少有機會能非常全面的瞭解兩位,並且很難得對兩位進行一個橫向的比較。首先,請兩位分別介紹一下自己。

equals

身世之謎
首先來說說我的身世吧。大家都知道,在Java世界裏面,有一個Object類,所有的其他類都繼承於他,他就是Java所有類的父類或祖先類,Object類裏面有一個equals方法,並且提供了默認的實現,如下代碼片段所示。

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

最佳編程實踐

敲黑板:從身世之謎中大家可以得知:如果一個自定義類沒有覆蓋equals方法,如代碼片段1所示,那麼該方法其實是用於判斷兩個對象是否是同一個對象。

當然,繼承於Object的自定義類是可以覆蓋equals方法的,但是覆蓋的時候需要滿足一些要求,以下通過一個例子來說明最佳編程實踐,如下代碼片段所示,代碼註釋中相關實踐步驟說明。

public boolean equals(Object otherObject){
    //1. 出於性能優化的考慮,首先判斷是否是自身比較 
    if(this == otherObject) return true; 
    //2. 出於安全性的檢測
    if(null == otherObject) return false;
    //3. 測試比較的對象是否是同一類型
    if(!(otherObject.getClass() == this.getClass())) return false;
    //4. 類型轉換
    PingPong other = (PingPong)otherObject;
    //5. 根據業務需要對需要比較的成員變量進行逐一比較
    //如果比較項都相同則返回爲true
    if(other.radius == this.radius) return true;
    return false;
}

==符號

身世之謎
==是一個操作符,操作符的左右兩邊變量既可以是基本類型也可是對象類型。當==應用於基本類型的時候,是用於判斷操作符左右兩邊的變量存儲的值是否相等;當==應用於對象類型的時候是用於判斷操作符左邊的對象是否是同一對象。

案例說明

boolean  ret;
int      i1     = 2;
int      i2     = 2;

float    f1 = 2.0f;
float    f2 = 2.0f;

double   d1 = 2.0;
double   d2 = 2.0;

String   s1 =   new String("abc");
String   s2     =   new String("abc");
String   s3 =   new String();

ret = (i1 == i2);     //true
ret = (f1 == f2);     //true;由於精度原因,不推薦
ret = (d1 == d2);     //true;由於精度原因,不推薦


ret = (s1 == s2);         //false
ret = (s1.equals(s2));    //true
ret = (s1.equals(s3));    //false
ret = (s1 == s2);         //false
s3  = s1;
ret = (s1 == s3);         //true

思考題

請老鐵們考慮下面代碼片段中的輸出結果,答案將在下篇文章中揭曉。

String str1 = "敲黑板";
String str2 = "敲黑板";
String str3 = new String("敲黑板");
boolean  ret;

ret = (str1 == str2);       //?
ret = (str1.equals(str2));  //?
ret = (str1 == str3);       //?
ret = (str1.equals(str3));  //?
ret = (str1 == str1.trim());    //?

小結

敲黑板,畫重點:

  1. equals是類的成員方法,只能用於對象之間的比較,不能用於基本類型;
  2. ==既可以用於對象之間的比較,也可以用於基本類型。
  3. 如果一個自定義類不覆蓋Object的equals方法,那麼equals就是用於判斷兩個對象是否是同一個引用,意即是否是指向同一內存區域的首地址。
  4. 如果自定義類覆蓋了Object的equals方法,那麼則按照該方法自定義的業務邏輯進行判斷,一般是用於判斷兩個對象的全部或部分內容是否相同。
  5. ==一方面可判斷基本類型的值是否相等。Java基本類型包括了浮點型(float、double);整型(byte、short、int、long);字符型(char);布爾型(boolean)。但是,由於精度的問題,不建議==用於浮點型的比較,可採用兩個浮點數相減並取絕對值,如果小於一個足夠小的數(比如1.E-6)就認爲是相等的。
  6. ==如果用於對象之間,則用於判斷兩者之間是否是同一個對象(此時與第3點中equals是可以互換的)。

彩蛋

NO.1 方法參數按“值”而非按“引用”方式傳遞 | Java敲黑板系列中留了一個思考題,其解答答案如下:

swap方法的參數p1和p2被初始化爲pt1和pt2兩個對象引用的拷貝,這個方法交換的是這兩個拷貝,並沒有改變存儲在變量pt1和pt2中的對象引用;爲此調用swap方法後,pt1和pt2變量的值並沒有發生變化。

轉載自公衆號:代碼榮耀
圖1

發佈了77 篇原創文章 · 獲贊 31 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章