getClass()和instanceof以及類的equals方法

在比較兩個類時,常見有兩種作法,一種是x.getClass() == y; 一種是x instanceof y,下面咱們來比較這兩種作法的區別。ide

getClass()返回一個對象所屬的類this

public static void main(String[] args) { Hero h1 = new Hero(null,10,2); Hero h2 = new Hero("zhang",10,2);
     Superman s1 = new Superman("zhang");
System.out.println(h1.getClass());
      System.out.println(h1.getClass() == h2.getClass());

      System.out.println(h1.getClass() == s1.getClass());
      System.out.println(s1.getClass() == h1.getClass());spa

 }
返回:
  class source.Hero

  true
  false
  falsecode

 

能夠看到,getClass返回的是一個類名,也就是說只會在類名相同時返回true,不會判斷子類與父類的繼承關係。對象

 

instanceof比較一個對象是不是該類的實例blog

public static void main(String[] args) { Hero h1 = new Hero(null,10,2); Hero h2 = new Hero("zhang",10,2); Superman s1 = new Superman("zhang"); System.out.println((h1 instanceof Hero)); System.out.println(h2 instanceof Superman); System.out.println(s1 instanceof Hero); System.out.println(h1 instanceof Superman); }
返回:

  true
  false
  true
  false繼承

能夠看到,instanceof會判斷繼承關係,子對象 instanceof 父類 會返回true,父對象 instanceof 子類會返回 false。 能夠理解爲判斷兩個問題:你是這個類嗎? 你是這個類的派生類嗎?get

 

equals方法:io

public boolean equals(Object otherObject) { if(this == otherObject) return true; if(otherObject == null) return false; if(getClass() != otherObject.getClass()) return false; Hero other = (Hero)otherObject; return name.equals(other.name) && hp == other.hp &&damage == other.damage; }

 

equals方法具備下面特性:class

1,自反性

2,對稱性

3,傳遞性

4,一致性

5,對於任意非空引用x,x.equals(null)應該返回false。

下面咱們首先結合上面的內容討論對稱性

father.equals(child)

這裏的father與child具備相同的姓氏,血型,家族。若是在Father.equals中用instanceof檢測,會獲得true。這意味着若是反過來調用:

child.equals(father)

也須要返回true。

應該這樣說:

1,若是子類擁有本身的相等概念,則對稱性需求將強制採用getClass進行檢測。 例如僱員和經理,對應的域相等就認爲兩個對象相等;若是兩個經歷對應的名字薪水僱傭日期都相等,而獎金不相等,就認爲他們不相同。

2,若是由超類決定相等的概念,那麼能夠用instanceof進行檢測,就能夠在不一樣的子類對象之間進行相等的比較。例如經理是僱員的兒子類,假設使用僱員的ID做爲相等的檢測條件,那麼這個相等概念也適用於經理,此時能夠用instanceof進行檢測,而且應該將Employee.equals方法聲明爲final。

 編寫完美equals方法的建議(來自CoreJava):

  1,顯式參數命名爲otherObject,稍後須要將它轉換成另外一個叫作other的變量 這裏參數必定是Object類型 不然不會產生Override

  2,檢測this和otherObject是否引用同一個對象

    

if(this == otherObject) return true;

 

  3,檢測otherObject是否爲null。若是是null,則返回false

  4,比較this和otherObject是否屬於同一個類。按照上面紅字的總結:若是equals的語義在每一個子類中有所改變,就用getClass檢測:

if (getClass() != otherObject.getClass()) return false;

  若是全部的子類都擁有統一的語義,就是用instanceof檢測

  

if (!(otherObject instanceof ClassName)) return false;

  5,將otherObject轉換爲相應的類類型變量:

ClassName other = (ClassName) otherObject;

  6,如今開始對全部須要比較的域進行比較。使用 == 比較基本類型域, 使用equals比較對象域。 

  

return field 1 == field2 && Objects.equals(field2,other.field2) &&....... ;

  這裏須要注意: 若是在兩個參數都爲null時須要返回true,那麼應該使用Objects.equals(1,2)

         若是不能接受有參數爲null,或者兩個參數不會爲null,則使用a.equals(b) (當有一個參數爲null時,a.equals(b)將會拋出NullPointerException)

   若是在子類中從新定義equals,就要在其中包含調用super.equals(other)

相關文章
相關標籤/搜索