類已經聲明了泛型參數 <E>,成員方法直接使用類級泛型參數即可,無需也不允許在方法上再次聲明 <E>。
public class GenericStack<E> {
// ...
public <E> void push(E e) { // 編譯錯誤:方法級 隱藏了類級 ,導致類型混淆
list.add(e);
}
}
public class GenericStack<E> { // 類聲明泛型參數 E
private ArrayList<E> list = new ArrayList<>();
public void push(E e) { // 直接使用類級 E,無需
list.add(e);
}
public E pop() { // 返回類級 E
// ...
}
}
**當方法需要的類型參數與類的泛型參數無關,或類本身不是泛型類時。**
public class CollectionUtils { // 非泛型類
// 方法自己聲明類型參數 T
public static <T> List<T> newArrayList() {
return new ArrayList<T>();
}
public static <T> void swap(List<T> list, int i, int j) {
T tmp = list.get(i);
list.set(i, list.get(j));
list.set(j, tmp);
}
}
public class Box<T> { // 類泛型 T
private T content;
// 方法需要新類型參數 U,與類的 T 無關
public <U> Box<U> transform(Function<T, U> mapper) {
return new Box<>(mapper.apply(content));
}
}
| 情況 | 方法聲明 | 示例 |
|---|---|---|
類有泛型 <E>,方法用同一個 E | 無 <E>,直接用 E | public void push(E e) |
| 類無泛型,方法需泛型 | 需 <T> | public static <T> List<T> emptyList() |
類有 <T>,方法需**另一個**類型 U | 需 <U> | public <U> Box<U> map(Function<T,U> f) |
| 構造函數 | **無** <T>,直接用類級參數 | public GenericStack() (或 public GenericStack(int cap)) |
類級泛型參數是類的「屬性」,成員方法天然可見並共享。 push(E e) 中的 E 直接引用類定義的 <E>,**不需要也不應該**在方法前加 <E>。只有當方法需要**獨立於類**的類型參數時,才在方法修飾符後聲明 <T>,這才叫「泛型方法」。