在比較兩個類時,常見有兩種作法,一種是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)