《Effective Java讀書筆記》--對於全部對象都通用的方法

equals

若是肯定一個函數不會被調用,請在函數中直接 throws   UnsupportException,防止程序邏輯出錯時還默默執行。 java

在改寫類的equals方法時,要實現以下的等價關係: 緩存

  • 自反性
  • 傳遞性
  • 對稱性
  • 一致性
  • 非空性——對任意非空引用值x,x.equals(null)必定返回false。

以下的equals代碼是一個很好的實踐: 函數

public boolean equals(Object o) {
	if (this == o) {
		return true;
	}
	if (!(o instanceof PhoneNum)) {
		return false;
	}
	PhoneNum pn = (PhoneNum) o;
	return pn.areaCode == this.areaCode && pn.num == this.num;
}




  • 傳入參數是Object,而不是其餘特化類型,保證了equals函數的重寫,而不是重載。
  • 用instanceof檢測傳入類型,傳入參數不是指望類型時就返回false。
  • 比較以前,爲了能正確訪問對象內的成員,先作了類型的強制強制轉換。

hashCode

改寫equals時,不要忘記同時改寫hashCode。在以下程序中,重寫了equesl,可是沒有重寫hashCode,因此輸出null,而不是mike。 this

import java.util.HashMap;
import java.util.Map;

public class Test {
	public static void main(String[] args) {
		HashMap m = new HashMap();
		m.put(new PhoneNum(0, 123456), "mike");
		String v = (String) m.get(new PhoneNum(0, 123456));
		System.out.println(v);
	}
}

class PhoneNum {
	private final int areaCode;
	private final int num;

	PhoneNum(int areaCode, int num) {
		this.areaCode = areaCode;
		this.num = num;
	}

	public boolean equals(Object o) {
		if (!(o instanceof PhoneNum)) {
			return false;
		}
		PhoneNum pn = (PhoneNum) o;
		return pn.areaCode == this.areaCode && pn.num == this.num;
	}
}


實現hashCode時,須要注意: spa

  • x.equals(y)返回true時,那麼x和y的hashCode必定要返回相同值。
  • 若是對象是非可變的,而且hashCode的計算很耗費資源,建議第一次計算hashCode後,就把它緩存到對象內部。

toString

老是要實現toString方法,System.out.println一個對象時,會調用toString方法。 code

clone

改寫clone函數會有不少「坑」,建議不該該去改寫clone方法。 對象

能夠有其餘途徑去提供對象拷貝的能力,好比拷貝構造函數。
public Yum(Yum yum);
或者是靜態工廠方法:
public static Yum newInstance(Yum yum);

拷貝構造函數有許多優勢,好比,能夠把類型A拷貝成類型B,而這是clone方法不能實現的。 接口

//該代碼經過拷貝構造函數,把LinkedList轉換成了ArrayList。
LinkedList<Integer> ll = new LinkedList<Integer>();
ll.add(1);
ll.add(2);
ArrayList<Integer> al = new ArrayList<Integer>(ll);
for (Integer i : al) {
    System.out.println(i);
}

compareTo

實現compareTo接口時,要注意: 資源

  • 傳遞性。 當x.compareTo(y) > 0 && y.compareTo(z) > 0爲真時,則x.compareTo(z) > 0。
  • 相對性。x.compareTo(y) > 0 則y.compareTo(y) < 0。x.compareTo(y)拋異常時,y.compareTo(x)也拋異常。
  • 建議保證 (x.compareTo(y) == 0) == (x.equsls(y))
  • x.compareTo(y) == 0 時,那麼x.compareTo(z) 和 y.compareTo(z)返回值同正負。
  • compareTo只是指定了返回值的符號,咱們能夠利用這一點來簡化比較的代碼:
public int compareTo(Object o) {
	PhoneNum pn = (PhoneNum) o; // 和equals方法不一樣,這裏強制轉化時,不須要作類型檢查。compareTo(null)和compareTo("TEST")分別拋出NullPointerException和ClassCastException正是咱們想要的。
	int areaCodeDiff = areaCode - pn.areaCode;
	if (0 != areaCodeDiff) {
		return areaCodeDiff;
	}
	return this.num - pn.num;
}
相關文章
相關標籤/搜索