一般在方法執行之前先檢查參數的有效性,如果參數值無效,那麼很快它就會失敗,並且清楚的拋出合適的異常。
如果這個方法沒有檢查參數的異常,那麼可能在方法處理中出現令人費解的異常。更糟糕的有可能是,方法可以正常返回,但是卻使得某個對象處於被破壞的狀態.
拋出異常
對於公有方法,可以在Javadoc中的@throw標籤來說明違反異常時所拋出的異常類型。一旦在文檔中說明了異常,那麼強加這些類型的異常檢測就會是比較容易的事情,例子如下:
// Modular Arithmetic Operations
/**
* Returns a BigInteger whose value is {@code (this mod m}). This method
* differs from {@code remainder} in that it always returns a
* <i>non-negative</i> BigInteger.
*
* @param m the modulus.
* @return {@code this mod m}
* @throws ArithmeticException {@code m} ≤ 0
* @see #remainder
*/
public BigInteger mod(BigInteger m) {
if (m.signum <= 0)
throw new ArithmeticException("BigInteger: modulus not positive");
BigInteger result = this.remainder(m);
return (result.signum >= 0 ? result : result.add(m));
}
上面這個例子是BigInteger中的求模方法,取模的時候需要其大於0,否則拋出異常。
斷言
另外,對於未被導出的方法,作爲包的創建者,你可以控制這個方法在哪些情況下可以被調用,因此你可以,也應該確保只將有效的參數傳遞進去。因此,非公有方法通常應該使用斷言(assert)來檢查它們的參數,如下:
private static void sort(long a[], int offset, int length) {
assert a != null;
assert offset >= 0 && offset <= a.length;
assert length >= 0 && length <= a.length - offset;
}
在生產環境中,一般是不支持assert的,因此這樣可以提高效率,沒有成本開銷。所以,assert只在私有方法中使用,因爲私有方法的調用者開發者,他和被調用者之間是一種弱契約關係,或者說沒有契約關係,其間的約束是依靠開發者自己控制的,開發者應該有充分的理由相信自己傳入的參數是有效的。所以,從某種角度上來說,assert只是起到一個預防開發者自己出錯,或者是程序的無意出錯。
另外
static List<Integer> intArrayAsList(final int[] a) {
if (a == null)
throw new NullPointerException();
return new AbstractList<Integer>() {
public Integer get(int i) {
return a[i]; // Autoboxing (Item 5)
}
@Override public Integer set(int i, Integer val) {
int oldVal = a[i];
a[i] = val; // Auto-unboxing
return oldVal; // Autoboxing
}
public int size() {
return a.length;
}
};
}
在上面的例子,傳入的是一個int數組,返回的是它的list視圖。如果傳入的是null,返回了一個新建的list,然後錯誤的null在後面的程序中可能會非常難以定位。因此,構造器檢查參數的有效性是非常重要的,必須保證構造出來的對象是有效的。