2009年5月13日 星期三

Practical Java Programming Language Guide-第二章 物件與相等性

這章節介紹了object與primitive types、equality等相關的觀念

case 8:區別reference type和primitive types
Java有兩大型別reference和primitive,primitive的效率會比較高,而reference可以有比較大的彈性,而每個primitive(基本型別)都有對應的wrapper object,像是int就有個Integer支援
reference在創建(new)的時候成本非常高,如果追求高效能的話則應該選用primitive
因為primitive的創建只在stack上,不用再去heap要記憶體(請參考http://hatsukiakio.blogspot.com/2009/04/c-static.html)
舉個例子

int i=5;
Integer j=new Integer(10);


i只用了Stack上的4個byte的記憶體,但是Integer除了stack上的4 byte(32 bit機器上指標的大小),在heap又用了一塊記憶體存真正的值加上對method的mapping,這之間效率比很明顯
但是不是說Integer不好,在很多情況下他也很方便
附帶一提,如果要寫swap函式的話不能用int,要用Integer理由請參考第一章第一個case

case 9:區分==和equals
equal()這函式在java舉足輕重,甚至有人主張所有類別都該複寫這個函式
因為java內建的==只能判別基本型別的相等,對於reference如果不複寫的話,他只會檢查兩變數是否是同一個instance,如果對物件邏輯上的相等有需求,都應該override這個函式

Integer a=new Integer(10);
Integer b=new Integer(10);
System.out.print(a==b);//false;


case 10:不要依賴equals()的預設實作
理由同case9 預設object的equal只是在使用==來做比較,只能比出兩個是否為同一實體

case 11:實作equals()時必須保持深思熟慮
這個case點出你應該好好設計equal

case 12:實作equals()時優先考慮使用getClass()
這邊是考慮『相同的class所產生的物件才可能相等』,不過這必須牽扯到superclass跟subclass是否也該考慮


class Base{

public boolean equals(Object obj)
{
if(obj==this)return true;
if(obj!=null&&getClass()!=obj.getClass())return false;
//otherwise
}
}

書上建議任何equal都可以用此方式當title,先檢查是不是自己,在檢察是不是null最後檢查是不是同個class

case 13:呼叫super.equals()以喚起base class的相關行為
這邊主要說,父類別的比較,交給父類別去做,不要自己做,避免產生不必要麻煩
但是要注意如果base class是Object就不要呼叫super.equals(),因為他是檢察是否為同一個實體

case 14:在equals()函式中謹慎使用instanceof
這邊牽扯到base class跟subclass之間的關連,子類別是父類別的一種,用instanceof他會通過
但是用getClass(),子類別跟父類別是不同類別所以不會通過


case 15:實作equals()遵循某些規則

  1. 如果class的兩物件及使佔用不同記憶體,也可被視為邏輯上相等,就該複寫equals();

  2. 先檢查是否等於this

  3. 比較兩物件的相關屬性判斷是否相等

  4. 如果java.lang,Object以外的父類別實作了equals(),就該呼叫super.equals()



在equals()中對getClass還是instanceof做取捨時該考慮的問題

  1. 如果只允許同一class才能相等才用getClass()

  2. 如果不得不考慮父類別與子類別的相等性,才應該使用instanceof,這其中複雜性很高

  3. 如果使用instanceof,而且父類別跟子類別都有實作equals(),比較能避免不對稱性


當然!這參考就好,真正的equal還是要視自己需求而定

沒有留言: