開心一笑
【一對夫婦避孕失敗后生了一個小男孩,孩子一生出來就緊握拳頭,一直笑個不停.護士把他的拳頭一掰開.發(fā)現(xiàn)里面有一把避孕藥,接著小男孩開口說話了:“你們兩個想弄死我,沒那么容易,哈哈哈】
提出問題
項目開發(fā)中,對象都通用的方法要注意那些???
解決問題

覆蓋equals時請遵守通用約定
先溫習下枯燥的理論知識,很無聊,但很重要。
- 自反性:對于任何非null的引用值x,x.equals(x)必須返回true.
- 對稱性:對于非空的引用值x,y,當且僅當x.equals(y)返回true時,y.equals(x)必須返回true.
- 傳遞性:對于任何非null的引用值x,y,z,如果x.equals(y)=true,y.equals(z)=true,那么x.equals(z)也必須返回true。
- 一致性:對于任何非null的引用值x,y,只要equals的比較操作在對象中所用的信息沒有被修改,多次調用x.equals(y)就會一致地返回true,或一致地返回false.
- 對于非null的引用值x,x.equals(null)必須返回false.
高質量equals方法的訣竅
- 使用==操作符檢查參數(shù)是否為這個對象的引用。
- 使用instanceof操作符檢查參數(shù)是否為正確的類型。
- 把參數(shù)轉換成正確的類型。
- 當編寫完成了equals方法之后,應該問自己三個問題,它是否是對稱的、傳遞的、一致的。
我用開發(fā)工具自動幫我生成equals方法:
@Override
public boolean equals(Object o) {
//使用==操作符檢查參數(shù)是否為這個對象的引用
if (this == o) return true;
//使用instanceof操作符檢查參數(shù)是否為正確的類型
if (!(o instanceof AyTest)) return false;
//把參數(shù)轉換成正確的類型
AyTest ayTest = (AyTest) o;
if (flowerNum != ayTest.flowerNum) return false;
return true;
}
覆蓋equals時總要覆蓋hashCode
覆蓋equals方法,必須覆蓋hashCode方法。如果不這樣做,就會違反Object.hashCode的通用約定,從而也導致該類無法結合所有基于散列的結合一塊正常運轉,這樣的結合包括HashMap、HashSet和Hashtable
//這里引用課本的例子,非原創(chuàng)
public final class PhoneNumber {
private final short areaCode;
private final short prefix;
private final short lineNumber;
public PhoneNumber(int areaCode, int prefix, int lineNumber) {
rangeCheck(areaCode, 999, "area code");
rangeCheck(prefix, 999, "prefix");
rangeCheck(lineNumber, 9999, "line number");
this.areaCode = (short)areaCode;
this.prefix = (short)prefix;
this.lineNumber = (short)lineNumber;
}
private static void rangeCheck(int arg, int max, String name) {
if (arg < 0 || arg > max) {
throw new IllegalArgumentException(name + ": " + arg);
}
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof PhoneNumber)) {
return false;
}
PhoneNumber pNumber = (PhoneNumber)o;
return (pNumber.lineNumber == lineNumber) && (pNumber.prefix == prefix) && (pNumber.areaCode == areaCode);
}
}
測試例子:
public static void hashCodePhoneNumber() {
Map<PhoneNumber, String> map = new HashMap<PhoneNumber, String>();
PhoneNumber phoneNumber = new PhoneNumber(707, 867, 9876);
map.put(phoneNumber, "Jenny");
//這里是重點 重點 重點 一個是new 出來的 一個是 原來的phoneNumber
System.out.println(map.get(new PhoneNumber(707, 867, 9876)));
System.out.println(map.get(phoneNumber));
}
執(zhí)行結果:
null
Jenny
解釋一下:
不去覆蓋hashCode,使用map.put時,我們是把這些PhoneNumber對象放在各個不同的盒子里,而我們去map.get()的時候,只是去某一個盒子里去找,而如果我們覆蓋了hashCode方法,這時,如果通過hashCode計算出來的值是相等的,就會放在同一個盒子里。這樣,只要我們對象中保存的值是完全一致的,就會找到這個key所對應的value。
始終要覆蓋toString
如果我們不覆蓋類的toString()方法,后果可能是當我們需要去打印這個類的對象時,會有一些并非是我們想要的那種結果。現(xiàn)在開發(fā)工具很方便,可以使用開發(fā)工具自動幫助我們生成。
謹慎的覆蓋clone
拷貝的含義是:
- x.clone() != x
- x.clone().getClass() == x.getClass()
- x.clone().equals(x)
覆蓋clone方法要非常小心,如果類里面含有復雜數(shù)據(jù)類型,要進行深度復制,如果類里面有final屬性,則無法進行clone,因為final屬性在clone時無法再進行賦值。
最好呢就是別去覆蓋這個方法,需要復制的話可以使用拷貝構造器和靜態(tài)拷貝工廠
考慮實現(xiàn)Comparable接口
comparaTo方法不是Object中的方法,而是Comparable接口中唯一的方法。該方法不僅可進行等同性比較,還可以進行順序比較。
接口的通用約定是按照equals方法來定義的,但有序集合使用了compareTo方法的等同性測試。
如果是是一個值類,而且具有明顯的內在排序關系,就因該堅決實現(xiàn)該接口。
如果你正在編寫一個值類,它具有非常明顯的內在排序關系,比如按字母順序、按數(shù)值順序或者按照年代順序,那就應該堅決考慮實現(xiàn)這個接口。
參考文章
【1】Effective Java:對于所有對象都通用的方法
【2】Java中equals和==的區(qū)別
【3】Effective Java——對所有對象通用的方法
【4】Effective Java 讀書筆記之二 對于所有對象都通用的方法
【5】考慮實現(xiàn)Comparable接口
讀書感悟
來自韓寒《我所理解的生活》
- 我所理解的生活就是做著自己喜歡的事情,養(yǎng)活自己,養(yǎng)活家人。生活不是攀爬高山,也不是深潛海溝,它只是在一張標配的床上睡出你的身形。我所理解的生活就是和自己喜歡的一切在一起。
- 緣分不是走在街上非要撞見,緣分就是睡前醒后彼此想念。
- 打死也不能放棄,窮死也不能嘆氣,要讓笑話你的人成為笑話。
- 可以后悔,但不留遺憾,有很多事情做了以后發(fā)現(xiàn)自己傻了或者失敗了,但還是要去做。
- 世間萬千種寵愛,無數(shù)種人心,得之我幸,不得我也沒什么不幸。
- 我相信真誠相待,也相信倒霉認栽。
- 每個人的道路都不同,我走在我的野路上,她走在她的大路上,都值得祝福。只要不走歪路邪路,每條道路都有成功的方式。
其他
如果有帶給你一絲絲小快樂,就讓快樂繼續(xù)傳遞下去,歡迎轉載,點贊,頂,歡迎留下寶貴的意見,多謝支持!