二。對於所有物件都通用的方法
主要介紹如何正確地改寫object類中的非final方法。
第7條:在改寫equals的時候請遵守通用的約定
改寫equals方法所必須遵守的幾個約定
1。自反性:x.equals(x)必須返回true
2。對稱性:y.equals(x)返回的必須和x.equals(y)一致
3。傳遞性:x.equals(y),y.equals(z)如果返回true的話,那麼x.equals(z)也必須返回true
4。一致性:多次呼叫x.equals(y)返回的值應該是一致的
5。非空性:x.equals(null)必須返回false
這裡最容易產生錯誤的是第2和第3條。要保證第2條你必須保證不擴大比較的物件的範圍。而第3條產生的問題一般在繼承的過程中,子類擴充套件了父類,增加了新的變數,涉及到物件導向關係理論的乙個基本問題,那就是:
要想在擴充套件乙個可例項化的類的同時,既要增加新的特徵,同時還要保留equals約定,沒有乙個簡單的方法可以做到這一點。
撰寫高質量的equals方法的一些處方或者說告戒:
a.使用"=="檢查引用是否為空
b.使用instanceof檢查物件的類別是否正確
c.把實參轉換到正確的型別,並保證實際引數中的"關鍵域"與當前物件中對應的域是否匹配
d.編寫完equals之後應該檢查是否滿足:對稱性,傳遞性,一致性
e.當你改寫equals的時候,總要改寫hashcode
f.不要企圖讓equals方法過於聰明,加入太多等價關係比較只會讓事情變糟糕
g.不要使equals方法依賴於不可靠的資源
h.不要使equals宣告中的object物件替換為具體的型別物件
不過,你可以用組合代替繼承,在新的類中加入乙個原有類的物件,而不是繼承它,這樣就不會遇到保持equals的問題了。
第8條:在改寫equals時總是要改寫hashcode
如果不這樣做的話,就導致該類無法與所有基於雜湊值的集合型別一起正常工作,如hashset,hashmap。乙個理想的雜湊函式應該把乙個集合中的不相等的物件均勻的分布到所有可能的雜湊值上,書中提供了一種方法接近理想狀態
1.把某個非0的常整數儲存在乙個叫result的int型變數中
2。對於物件中的每乙個關鍵域f完成下列步驟
a。為該域計算雜湊碼c:
i.如果是boolean f?0:1
ii.byte,char,shor,int型 (int)f
iii.long型 (int)(f^(f>>32))
ivfloat型 float.floattointbits(f)
v.double型 double.doubletolongbits(f)得到乙個long型,然後按iii計算
vi.如果是乙個物件引用可以遞迴呼叫hashcode()或者計算乙個另外的「規範表示」
vii。如果是乙個陣列,則把每乙個元素當作乙個單獨的域來處理
b.按公式計算雜湊碼 result=37*result+c;
3。返回result
還一點,一定要包括該類的關鍵性的變數,不要試圖通過排除乙個物件的關鍵部分來獲得效能的提高
第9條:總是改寫tostring()
這一條更多的是為了提供更有價值的資訊給使用者,我很少使用這點,慚愧
第10條:謹慎地改寫clone()
實現物件的深層拷貝。可以這樣認為,clone()方法是另乙個建構函式!要編寫乙個行為正確的clone()方法,特別是對於一些類的內部具有可變的域是相當困難的。首先你必須實現cloneable介面,在clone()方法中呼叫super.clone(),然後修改任何需要修改的變數。例如,要對上一騙文章的stack撰寫乙個正確的clone方法如下
public object clone() throws clonenotsupportedexception{
stack result=(stack)super.clone();
result.elements=(object)elements.clone();
return result;
前提要求elements不是final.
clone()方法的改寫是複雜的,甚至是危險的,還有另一種方法來提供拷貝物件的功能,那就是拷貝建構函式。這同樣不是c++專有的概念。
例如public example(example),你傳入乙個同型別的物件,然後在這個建構函式中做變數的拷貝就ok了。相比於cloneable介面的複雜度,這是乙個更好的解決辦法。
第11條:考慮實現***pareable介面
此介面的實現類似於equals方法,也要保持對稱,傳遞,一致等特性,具體不再介紹,如果你需要對某個類的物件實行排序等演算法或者與collections framework中的類打交道,你該考慮實現這個介面
Effective Java 學習筆記 6
及時消除不使用的物件的引用,理論上,帶有記憶體管理的語言是不存在記憶體洩漏的,但是如果對物件的操作不當,也是可能會造成記憶體洩漏.如有乙個stack,其pop函式如下.public object pop if element.length 0 return null return element s...
Effective Java 學習筆記(5)
盡量復用物件,而不是建立新的物件,特別是當乙個物件是immutable 不可改變 的時候。如string物件,string s new string string 千萬不要這樣做,因為這裡實際上建立了兩個物件。要避免出現這樣的情況,1是可以用靜態工廠函式,來解決,如類庫中的boolean.value...
Effective Java 學習筆記 6
及時消除不使用的物件的引用,理論上,帶有記憶體管理的語言是不存在記憶體洩漏的,但是如果對物件的操作不當,也是可能會造成記憶體洩漏.如有乙個stack,其pop函式如下.public object pop if element.length 0 return null return element s...