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


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

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

    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());


    }
返回:
  class source.Hero

  true
  false
  false

 

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

 

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

    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。 可以理解為判斷兩個問題:你是這個類嗎? 你是這個類的派生類嗎?

 

equals方法:

    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方法具有下面特性:

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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM