首先,我推薦大家先看下equals 和 == 的區別一文再繼續往下看本文(雖然文中有些解釋還是讓人有點感覺不對),因為我就是從園友@一沐陽光的這篇文章中滋生出的問題,才寫的本文。當然你也可以直接看本文,因為我並沒有把本文與它強行聯絡在一起。
先來看下面的**:
11、bo1=true。這點是沒有疑問的,值型別的比較,就是比較它的值。int i1 = 8;2
int i2 = 8;3
bool bo1 = i1 == i2; //
true
4bool bo2 = (object)i1 == (object)i2; //
false
5bool bo3 = i1.equals(i2); //
true
6bool bo4 = i1.equals((object)i2); //
true
7bool bo5 = ((object)i1).equals(i2); //
true
2、bo2=false。這是把兩個int型的值型別裝箱了,然後「==」比較時,是比較其引用的位址,所以為false。
3、bo3=true。這是呼叫了int對應的int32的equals(int)方法:
1很顯然,this就是i1,obj就是i2,最終返回的還是i1==i2,為true。public
bool equals(int
obj)
2
4、bo4=true。可能我們經常都認為equals(object)是繼承自object類:
1但經常忽略了一點,它是個virtual方法,像int32、uint32、double、string等等常用型別,都是重寫了這個方法的,而int對應的int32型別重寫為:public
virtual
bool equals(object
obj)
2
1所以遇到i1.equals(i2),首先呼叫了(obj is int)來判斷i2是不是int型的,如果是就會有強制轉化,實際上執行返回的是 i1==(int)((object)i2) ,可見,這必然也是true。public
override
bool equals(object
obj)
2
其它型別的重寫也與這類似,都會首先判斷引數obj是不是當前型別,是則強制轉化,再進行比較,如果不是,則看情況進行處理。這裡說的看情況,主要包括了兩種情況:第一種,本身是值型別。嘗試轉化引數的型別,如果引數與本身型別相同,這時直接呼叫==號進行比較(也有特殊情況),如果引數與本身型別不同,則返回false;第二種,本身是引用型別(注意string是引用型別),會嘗試轉化引數為本身的型別,失敗則直接返回false,否則再比較引用的位址是否相同,進行返回。string是引用型別中的特例,不僅引用位址相同的string可以為真,內容相同的string比較也為真,可以看下面關於string型別的equals(object)重寫方法:
1說明一下,最後的equalshelper(this,strb)函式內部就是對這兩個字串的內容進行逐字元地比較了。public
override
bool equals(object
obj)27
string strb = obj as
string;8
if (strb == null)9
12if (object.referenceequals(this
, obj))
1316
if (this.length !=strb.length)
1720
return equalshelper(this
, strb);
21 }
5、bo5=ture。這與前面的bo3、bo4並不一樣了,這時編譯器呼叫的不是int32的equals(int)或equals(object)方法,而確實就是object型別的equals(object)方法,通過il**得知的,i1是通過(object)i1手動裝箱的,而i2則是協變,自動完成裝箱:
1 il_0032: ldloc.0那麼此時為什麼又相等了,注意前面貼的關於object的**中,只有一行:runtimehelpers.equals(this, obj);這句話我使用reflector也沒有找到具體實現,目測應該是用於幫助編譯器實現執行時**生成工作的,在其內部可能實現了轉化,會在執行期根據i1的型別,再呼叫int32的equals方法來完成最終比較。為了驗證我的想法,我在msdn上找到了下面關於runtimehelpers.equals(object, object)的話:// 讀取i0
2il_0033: box [mscorlib]system.int32 // 裝箱
3 il_0038: ldloc.1 // 讀取i1
4il_0039: box [mscorlib]system.int32 // 裝箱
5 il_003e: callvirt instance bool [mscorlib]system.object::equals(object
) // 呼叫object.equals(object)方法
6 il_0043: stloc.s bo5 // 儲存結果到bo5
提供一組為編譯器提供支援的靜態方法和屬性。無法繼承此類。由於(object)i1與(object)i2並不是同乙個例項,二者又均不為null,所以進入i1.equals(i2)的邏輯運算階段,最終返回true。本文就此完結,這樣一來,結合最開始貼出的文章,最少我自己已經能大概搞清楚實際發生了什麼,而不需要去死記了,也不會在遇到這種情況時不知所措了。返回值如果 o1 引數與 o2 引數是同乙個例項,或者二者均為 null,或者 o1.equals(o2) 返回 true,則為 true;否則為 false。
ArrayList需要了解的事情
arraylist 是日常開發經常使用到的容器類。它能夠方便的進行資料的查詢 替換。但是因為其低層實現的原因在資料容量 效能 執行緒安全上都存在問題,主要涉及到下面的內容 1 預設初始容量為 0,如果未指定容量則首次初始的容量為 10 同時其也是有容量限制的 2 新增元素會涉及到陣列擴容和陣列元素拷...
2014暑假總結 美好的事情即將發生
暑假快結束了,總結這一年的收穫吧,這一年過的特別快,沒有就一年過去了,可是收穫卻不少。總結分享一下。潤物細無聲 公尺老師常常說他的學習方法是潤物細無聲的,這一點自己的感受特別多。今年一開始做的人事項目的時候,剛開始時不自信還是存在的,可是慢慢的發現自己的對於整個系統的認識和 編寫上手還是非常快的,自...
STL 迭代器刪除,插入元素發生的事情
一,序列式容器 1,刪除迭代器指向的元素 對於序列式容器 vector deque list 刪除當前的iterator會使後面所有元素的iterator都失效。這是因為vector,deque使用了連續分配的記憶體,刪除乙個元素導致後面所有的元素會向前移動乙個位置。使用erase方法後,返回的是下...