轉(zhuǎn)自:http://blog.csdn.net/CodingMouse/article/details/4064007
今天實(shí)現(xiàn)了一個(gè)較實(shí)用的Pojo(實(shí)體)基類
呵呵!也許你會(huì)覺得就單單重寫了Object根類的equals、hashCode、toString這三個(gè)方法有什么意義?
實(shí)質(zhì)上,如果你封裝過泛型集合基類,并在泛型集合基類中玩過根據(jù)自定義屬性排序的話,那么你會(huì)發(fā)現(xiàn)實(shí)現(xiàn)這樣的一個(gè)Pojo基類很有必要!
先看看代碼的實(shí)現(xiàn):
眾所周知,String 、Math、還有包裝類(如:Integer、Float、Double、Boolean等)都重寫了Object的equals方法,這樣才使得它們不再比較引用(某些地方也稱為“句柄”,“句柄”一詞貌似在Windows操作系統(tǒng)中經(jīng)常使用,如“窗口句柄”),而是比較內(nèi)容(值)相等。因?yàn)?,Object的equals()方法比較的是地址值。
特別需要注意的是:
Java語言對(duì)equals()的要求如下,
對(duì)稱性:如果x.equals(y)返回是“true”,那么y.equals(x)也應(yīng)該返回是“true”。
反射性:x.equals(x)必須返回是“true”。
類推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也應(yīng)該返回是“true”。
還有一致性:如果x.equals(y)返回是“true”,只要x和y內(nèi)容一直不變,不管你重復(fù)x.equals(y)多少次,返回都是“true”。
任何情況下,x.equals(null),永遠(yuǎn)返回是“false”;x.equals(和x不同類型的對(duì)象)永遠(yuǎn)返回是“false”。
那么,又為什么要重寫hashCode方法呢?網(wǎng)上的一些文章中是這樣描述的:
我們應(yīng)該先了解java判斷兩個(gè)對(duì)象是否相等的規(guī)則。
在Java的集合中,判斷兩個(gè)對(duì)象是否相等的規(guī)則是:
首先,判斷兩個(gè)對(duì)象的hashCode是否相等;
如果不相等,認(rèn)為兩個(gè)對(duì)象也不相等;
如果相等,則判斷兩個(gè)對(duì)象用equals運(yùn)算是否相等;
如果不相等,認(rèn)為兩個(gè)對(duì)象也不相等;
如果相等,認(rèn)為兩個(gè)對(duì)象相等;
我們?cè)趀quals方法中需要向下轉(zhuǎn)型,效率很低,所以先判斷hashCode方法可以提高效率。
一般來說,如果你要把一個(gè)類的對(duì)象放入集合中,那么通常要為其重寫equals()方法,讓它們比較地址值而不是內(nèi)容值。特別地,如果要把你的類的對(duì)象放入散列中,那么還要重寫hashCode()方法;要放到有序容器中,還要重寫compareTo()方法。
另外,網(wǎng)上也有這樣的一段描述:
關(guān)于在hibernate的pojo類中,重新equals()和hashcode()的問題:
1),重點(diǎn)是equals,重寫hashCode只是技術(shù)要求(為了提高效率)
2),為什么要重寫equals呢,因?yàn)樵趈ava的集合框架中,是通過equals來判斷兩個(gè)對(duì)象是否相等的
3),在hibernate中,經(jīng)常使用set集合來保存相關(guān)對(duì)象,而set集合是不允許重復(fù)的。我們?cè)賮碚務(wù)勄懊嫣岬皆谙騢ashset集合中添加元素時(shí),怎樣判斷對(duì)象是否相同的準(zhǔn)則,前面說了兩條,其實(shí)只要重寫equals()這一條也可以。
但當(dāng)hashset中元素比較多時(shí),或者是重寫的equals()方法比較復(fù)雜時(shí),我們只用equals()方法進(jìn)行比較判斷,效率也會(huì)非常低,所以引入了hashcode()這個(gè)方法,只是為了提高效率,但是我覺得這是非常有必要的(所以我們?cè)谇懊嬉詢蓷l準(zhǔn)則來進(jìn)行hashset的元素是否重復(fù)的判斷)。
比如可以這樣寫:
public int hashCode(){
return 1;
} // 等價(jià)于hashcode無效
這樣做的效果就是在比較哈希碼的時(shí)候不能進(jìn)行判斷,因?yàn)槊總€(gè)對(duì)象返回的哈希碼都是1,每次都必須要經(jīng)過比較equals()方法后才能進(jìn)行判斷是否重復(fù),這當(dāng)然會(huì)引起效率的大大降低。
效率影響的體現(xiàn)可以在hashset、hashmap、hashtable、LinkedHashMap等帶hash字樣的集合中去測(cè)試,這里就不演示了。
至于為什么我要重寫toString方法,有兩點(diǎn)理由:
1、作為hashCode生成算法的一部分,與其內(nèi)容直接相關(guān),有更好的散列效果。
2、便于獲取其子類更詳細(xì)的內(nèi)容描述,便于調(diào)試,而不是得到諸如“java.lang.Object@757aef”這樣讓人難以理解的文字內(nèi)容。
我自己也編寫了一個(gè)測(cè)例:
- package com.china.codingmouse.cmsdk4j.example.pojo.test;
-
- import java.sql.Timestamp;
-
- import com.china.codingmouse.cmsdk4j.example.pojo.UserPojo;
-
-
-
-
-
-
- public class UserPojoEqualsAndHashCodeTest {
-
-
-
-
-
- public static void main(String[] args) {
-
- UserPojo up1 = new UserPojo(3, "鄧超", true, 25, "四川隆昌", new Timestamp(System.currentTimeMillis()));
- UserPojo up2 = new UserPojo(3, "鄧超", true, 25, "四川隆昌", new Timestamp(System.currentTimeMillis()));
- System.out.println("User1的內(nèi)容:" + up1);
- System.out.println("User2的內(nèi)容:" + up2);
- System.err.println("User1的散列碼:" + up1.hashCode());
- System.err.println("User2的散列碼:" +up2.hashCode());
- System.out.println("測(cè)試User1與User2地址(==)相等:" + (up1 == up2));
- System.out.println("測(cè)試User1與User2內(nèi)容(equals)相等:" + up1.equals(up2));
- UserPojo up3 = new UserPojo(6, "CodingMouse", false, 22, "中華人民共和國四川成都", new Timestamp(System.currentTimeMillis()));
- UserPojo up4 = new UserPojo(13, "Michael Jackson", false, 53, "美利堅(jiān)合眾國紐約市唐人街", new Timestamp(System.currentTimeMillis()));
- System.out.println("User3的內(nèi)容:" + up3);
- System.out.println("User4的內(nèi)容:" + up4);
- System.err.println("User3的散列碼:" +up3.hashCode());
- System.err.println("User4的散列碼:" +up4.hashCode());
- System.out.println("測(cè)試User3與User4地址(==)相等:" + (up3 == up4));
- System.out.println("測(cè)試User3與User4內(nèi)容(equals)相等:" + up3.equals(up4));
-
- }
-
- }
在Eclipse3.3控制臺(tái)輸出的最終的運(yùn)行結(jié)果為:
User1的內(nèi)容:[true, 25, 2009-04-10 18:39:54.557, 四川隆昌, 鄧超, 3]
User2的內(nèi)容:[true, 25, 2009-04-10 18:39:54.557, 四川隆昌, 鄧超, 3]
User1的散列碼:524379269
User2的散列碼:524379269
測(cè)試User1與User2地址(==)相等:false
測(cè)試User1與User2內(nèi)容(equals)相等:true
User3的內(nèi)容:[false, 22, 2009-04-10 18:39:54.563, 中華人民共和國四川成都, CodingMouse, 6]
User4的內(nèi)容:[false, 53, 2009-04-10 18:39:54.563, 美利堅(jiān)合眾國紐約市唐人街, Michael Jackson, 13]
User3的散列碼:-715569909
User4的散列碼:956891732
測(cè)試User3與User4地址(==)相等:false
測(cè)試User3與User4內(nèi)容(equals)相等:false
反正自我感覺挺良好的,如果您覺得有不妥的地方,還煩請(qǐng)幫忙指出為感!