《Effective Java》第 7 條款強調:優先考慮泛型方法。泛型方法比非泛型方法更安全、更易用,能在編譯期捕獲型別錯誤,避免執行期 ClassCastException。本文透過實例展示泛型方法重構、泛型靜態工廠與泛型單例工廠模式。
public static Set union1(Set s1, Set s2) {
Set result = new HashSet(s1);
result.addAll(s2);
return result;
}
// 呼叫時需強制轉型,不安全
Set raw = union1(set1, set2);
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
Set<E> result = new HashSet<>(s1);
result.addAll(s2);
return result;
}
// 呼叫時自動推導型別,完全型別安全
Set<String> safe = union(set1, set2);
關鍵差異:方法簽名宣告型別參數 <E>,參數與回傳值使用 Set<E>,編譯器自動推導實際型別。
Java 7 前建構子需重複指定型別參數:
Map<String, List<String>> map = new HashMap<String, List<String>>(); // 冗長
利用泛型靜態工廠方法,利用型別推導簡化:
public class GenericStaticFactory {
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap<K, V>();
}
}
// 使用:型別自動推導為 String, List<String>
Map<String, List<String>> anagrams = GenericStaticFactory.newHashMap();
Java 7+ 引入鑽石運算子 <> 後此模式較少見,但理解其原理有助於設計流暢 API。
實現單一實例服務多種型別參數的需求:
public class GenericSingletonFactory {
// 單一 Object 實例
private static UnaryFunction<Object> IDENTITY_FUNCTION =
new UnaryFunction<Object>() {
public Object apply(Object arg) { return arg; }
};
// 利用型別擦除與無檢查轉型,安全地服務所有型別
@SuppressWarnings("unchecked")
public static <T> UnaryFunction<T> identityFunction() {
return (UnaryFunction<T>) IDENTITY_FUNCTION;
}
}
核心原理:
UnaryFunction<Object> 實例接受任何物件並原樣回傳(UnaryFunction<T>) 適配任意型別identityFunction() == identityFunction() 為 trueString[] strings = {"jute", "hemp", "nylon"};
UnaryFunction<String> sameString = identityFunction();
for (String s : strings) System.out.println(sameString.apply(s));
Number[] numbers = {1, 2.0, 3L};
UnaryFunction<Number> sameNumber = identityFunction();
// 驗證單例特性
Object t1 = sameString;
Object t2 = sameNumber;
System.out.println(t1 == t2); // true,同一實例
@SuppressWarnings("unchecked") 但邏輯安全掌握這三種模式,能設計出更優雅、更安全、更易用的 Java API。這正是《Effective Java》倡導的核心哲學:讓編譯器為你工作,在編譯期發現錯誤。