《Effective Java讀書筆記》--方法

檢查參數的有效性

方法在執行前,首先對參數進行檢查,若是參數不合法,應該清楚地以一個適當的異常指明錯誤的緣由。
對於非公有方法,調用者應該保證傳入的參數是合理的,因此應該以assert斷言參數的有效性。
但「檢查參數的有效性」這條規則也有例外,好比檢查工做十分昂貴,或者不切實際,而且在計算過程當中有效性檢查工做也被隱含完成時。

須要時使用保護性拷貝

public class Period {
	private final Date start;
	private final Date end;

	public Period(Date start, Date end) {
		// if (start.compareTo(end) > 0) { //不是線程安全的
		// throw new IllegalArgumentException();
		// }
		//
		// this.start = start;
		// this.end = end;

		this.start = new Date(start.getTime()); // 保護性拷貝是在檢查參數有效性以前進行。
		this.end = new Date(end.getTime());

		if (this.start.compareTo(this.end) > 0) {
			throw new IllegalArgumentException();
		}
	}

	public Date start() {
		// return this.start;
		return (Date) this.start.clone();
	}

	public Date end() {
		// return this.end;
		return (Date) this.end.clone();
	}
}

Period中被註釋掉的代碼,沒有采用保護性的拷貝。這樣的話,Period保存的是兩個引用,start和end返回的也是引用,那麼用戶能夠經過引用改變Period的狀態,致使start>end非法狀況出現。 java

注意到Period的構造方法中,保護性拷貝是在檢查參數有效性以前進行,爲何呢? 數組

這是爲了線程安全考慮。假如線程A恰好執行完參數有效性檢查,OK了,而後緊接的執行線程B,線程B改變了end的值,使start>end。輪到線程A執行了,有效性檢查OK了,開始拷貝..此時start和end的值已經不合法了。 安全

謹慎使用重載方法

java中,重載方法的選擇是在編譯時決定的,跟類的多態不一樣。因此有些時候代碼行爲可能出乎咱們的意料。 this

好比以下代碼輸出的是三個"unknow",而不是分別輸出"set""list""unknow" spa


public class Test {

	public static String classify(Set s) {
		return "set";
	}

	public static String classify(List l) {
		return "list";
	}

	public static String classify(Collection c) {
		return "unknow";
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Collection[] c = new Collection[] { new HashSet(), new ArrayList(),
				new HashMap().values() };

		for (Collection collection : c) {
			System.out.println(classify(collection)); // 重載方法的選擇是在編譯時決定的,由於collection的類型是Collection,因此選擇第三個重載方法。
		}
	}
}
爲了使如上代碼按照咱們所想象的那樣工做,應該在Collection的重載方法中,用instanceof判斷參數的具體類型再作具體的邏輯。


對於重載方法,最好仍是別用了吧... 線程

看看java的ObjectOutputStream類,它的write方法沒有采用重載,而是採用了變形方法:writeBoolean(boolean) writeInt(int) writeLong(long)

返回0長度的數組而不是null

常常能夠看到以下代碼:
public Cheese[] getCheeses() {
    if (cheeseInstock.size() == 0) {
    return null;
    ......
    }
}
這樣,用戶使用這個接口時,還要寫額外代碼去判斷數組是否爲null,這很容易出錯,建議應該返回0大小的數組而不是null。
相關文章
相關標籤/搜索