第6章 通用物件操作

2022-03-25 07:19:16 字數 2692 閱讀 2443

6.1 物件的等值性與唯一性

system.object型別中的equals方法是比較兩個引用,如果指向的是同乙個物件則返回true,否則在任何其他情況下都返回false

當重寫自己的equals方法時,必須確保它遵循以下4條規則:

1、equals方法必須是自反的,也就是說x.equals(x)必須返回true

2、equals方法必須是對稱的,也就是說x.equals(y)和y.equals(x)必須返回同樣的值

3、equals方法必須是可傳遞的,也就是說如果x.equals(y)和y.equals(z)都返回true,x.equals(z)也必須返回true

4、equals方法必須是前後一致的,也就是說如果兩個物件的值沒有發生改變那麼多次呼叫equals方法的返回值應該相同

6.1.1 為基類沒有重寫object.equals方法的引用型別實現equals

為基類沒有重寫object.equals方法的引用型別實現equals方法,應首先判斷被比較的物件不為null,再判斷比較的兩個物件型別相同,之後將被比較的物件型別轉換後分別比較兩個物件的引用型別欄位和值型別字段

比較引用型別欄位應呼叫object的靜態equals方法,引數為兩個object物件。該方法對出現null的情況做了正確的檢測,而如果refobj為null時呼叫refobj.equals(other.refobj)將會丟擲nullreferenceexception異常

比較值型別欄位就應該呼叫該欄位型別的equals方法,而不應該呼叫object的靜態equals方法,因為值型別物件的值永遠不可能為null,且呼叫object的靜態equals方法會對值型別物件執行裝箱操作

6.1.2 為基類重寫了object.equals方法的引用型別實現equals

與基類沒有重寫object.equals方法相比,基類重寫了object.equals方法的實現與其基本相同,只是通常需要在比較前首先呼叫base.equals方法,先讓基型別比較其中的字段

但如果呼叫base.equals會導致直接呼叫object.equals方法則不應該再呼叫它,因為只有在兩個引用指向同乙個物件時object.equals方法才會返回true

6.1.3 為值型別實現equals方法

system.valuetype.equals方法在內部首先使用反射機制來得到型別的所有例項字段,再比較它們是否相等。這種比較的過程效率很低,但卻是乙個所有值型別都能繼承的相當不錯的預設實現

因為valuetype提供的equals實現效率不高,所以我們也應該對定義的值型別提供自己的equals實現。我們還應該為值型別定義乙個強型別版本的equals方法,讓其接受自身的值型別作為引數,這樣可以避免一些額外的裝箱操作

6.1.4 equals方法與==/!=操作符的實現總結

編譯器對它認為的基元型別提供了==和!=操作符實現,也重寫了equals方法

對自己定義的引用型別,我們應重寫equals方法,如果其基型別沒有繼承object.equals方法的實現,那麼我們應該呼叫基型別的equals方法。如果願意,我們還可以過載==和!=操作符讓它們呼叫重寫後的equals方法

對值型別,我們應該為其定義乙個型別安全的equals來比較物件的狀態,然後在實現「非型別安全」的equals時在內部呼叫型別安全的版本,(譯註說這樣可能有隱式轉換的問題,但是由於值型別是密封的,我還沒有想到怎樣在乙個新的型別中定義乙個和該型別之間的隱式轉換)我們還應該過載==和!=操作符,讓它們內部呼叫型別安全的equals方法。

(為什麼==和!=操作符對值型別是「應該」過載而引用型別是「可以」過載?「應該」過載是只是為了減少裝拆箱操作還是有其他原因?「可以」過載表示什麼情況下可以不過載?感覺不會用到就可以不過載?)

6.1.5 物件唯一性識別

object的靜態referenceequals方法判斷兩個引用是否指向同乙個物件。c#中我們也可以使用==來代替object.referenceequals方法,但==操作符只有兩邊的變數都為system.object型別時才會正確的比較引用是否相同,所以一般不要用==來判斷兩個物件引用是否相同

注意對值型別物件x呼叫referenceequals(x, x),結果會是false,因為x被兩次裝箱到不同的物件中去了

6.2 物件的雜湊碼

system.object提供了乙個gethashcode虛方法,使我們可以從任何物件上得到乙個int32型別的雜湊碼

如果我們定義了乙個型別並重寫了equals方法,那麼我們也應該重寫gethashcode方法,因為system.collections.hashtable型別的實現要求任何兩個相等的物件都必須有相同的雜湊碼值,所以我們需要確保用來判等的演算法和用來計算物件雜湊碼的演算法一致

6.3 物件轉殖

有時我們會希望得到乙個現有物件的拷貝,但對於某些型別如system.threading.thread,轉殖其物件例項毫無意義,另外對於某些型別,當構造乙個例項時該例項會被加入到乙個鍊錶或其他某種資料結構中,這時候簡單的物件轉殖可能會破壞該型別的語義

如果希望自己的例項被轉殖,類應該實現icloneable介面。該介面只定義了乙個方法clone,並且沒有顯示表明clone方法應該實現乙個淺拷貝還是深拷貝,所以我們必須自己決定。我們可以呼叫system.object的受保護方法memberwiseclone來實現淺拷貝

筆記 《js權威指南》 第6章 物件

1.屬性的特性 可寫性,可遍歷,可刪除修改屬性。2.物件的特性 1 物件的原型prototype,本物件的屬性繼承自它的原型物件。2 物件的類class,是乙個標識物件型別的字串。3 ecmscript 5中 物件的擴充套件標記指明了是否可以給該物件新增新屬性。3.物件的型別 1 內建物件 由ecm...

第6章 物件導向基本特徵

訪問控制修飾符的作用是控制類中的成員可以在哪些範圍內被訪問到 用的最多的有2個 public 公共的意思,訪問範圍最大,可以任意範圍內訪問 private 私有的意思,訪問範圍最小,只能在本類中被訪問 類中的要素,屬性,方法,構造器,塊,成員內部類,這些要素都隸屬於類,對於本類而言,這些要素就是互為...

第6章 物件與方法 筆記十一

第6章 物件與方法 實驗6.1 物件與方法實驗 利用oop,按照要求,完成如下任務 1 利用正方形類squa和長方形類rect,輸出預設邊長和周長以及 修改屬性值之後的邊長和周長,新增正方形的面積和長方形的面積 兩個方法,輸出預設面積以及修改屬性值後的面積 class squa length 10d...