我們在上面提到了, List> 中的元素只能使用 Object 來引用, 這樣作肯定時不太方便的, 不過幸運的是, Java 的泛型機制允許我們對泛型參數的類型的上界和下界做一些限制, 例如 List extends Number> 定義了泛型的上界是 Number, 即 List 中包含的元素類型是 Number 及其子類. 而 List super Number> 定義了泛型的下界, 即 List 中包含的是 Number 及其父類. 當引入了泛型參數的上界和下界后, 我們編寫代碼相對來說就方便了許多, 不過也引入了新的問題, 即我們在什么時候使用上界, 什么時候使用下界, 以及它們的區別和限制到底時什么? 下面我來說說我的理解.
? extends T
? extends T 描述了通配符上界, 即具體的泛型參數需要滿足條件: 泛型參數必須是 T 類型或它的子類, 例如:
List extends Number> numberArray = new ArrayList(); // Number 是 Number 類型的
List extends Number> numberArray = new ArrayList(); // Integer 是 Number 的子類
List extends Number> numberArray = new ArrayList(); // Double 是 Number 的子類
上面三個操作都是合法的, 因為 ? extends Number 規定了泛型通配符的上界, 即我們實際上的泛型必須要是 Number 類型或者是它的子類, 而 Number, Integer, Double 顯然都是 Number 的子類(類型相同的也可以, 即這里我們可以認為 Number 是 Number 的子類).
我們不能添加 Number 到 numberArray 中, 因為 numberArray 有可能是List 類型
我們不能添加 Integer 到 numberArray 中, 因為 numberArray 有可能是 List 類型
我們不能添加 Double 到 numberArray 中, 因為 numberArray 有可能是 List 類型
即, 我們不能添加任何對象到 List extends T> 中, 因為我們不能確定一個 List extends T> 對象實際的類型是什么, 因此就不能確定插入的元素的類型是否和這個 List 匹配. List extends T> 唯一能保證的是我們從這個 list 中讀取的元素一定是一個 T 類型的.
? super T
? super T 描述了通配符下界, 即具體的泛型參數需要滿足條件: 泛型參數必須是 T 類型或它的父類, 例如:
// 在這里, Integer 可以認為是 Integer 的 "父類"
List super Integer> array = new ArrayList();
// Number 是 Integer 的 父類
List super Integer> array = new ArrayList();
// Object 是 Integer 的 父類
List super Integer> array = new ArrayList();
關于讀取
對于上面的例子中的 List super Integer> array 對象:
我們不能保證可以從 array 對象中讀取到 Integer 類型的數據, 因為 array 可能是 List 類型的.
我們不能保證可以從 array 對象中讀取到 Number 類型的數據, 因為 array 可能是 List 類型的.
Producer extends: 如果我們需要一個 List 提供類型為 T 的數據(即希望從 List 中讀取 T 類型的數據), 那么我們需要使用 ? extends T, 例如 List extends Integer>. 但是我們不能向這個 List 添加數據.
Consumer Super: 如果我們需要一個 List 來消費 T 類型的數據(即希望將 T 類型的數據寫入 List 中), 那么我們需要使用 ? super T, 例如 List super Integer>. 但是這個 List 不能保證從它讀取的數據的類型.
如果我們既希望讀取, 也希望寫入, 那么我們就必須明確地聲明泛型參數的類型, 例如 List.
例子:
public class Collections {
public static void copy(List super T> dest, List extends T> src)
{
for (int i=0; i
上面的例子是一個拷貝數據的代碼, src 是 List extends T> 類型的, 因此它可以讀取出 T 類型的數據(讀取的數據類型是 T 或是 T 的子類, 但是我們不能確切的知道它是什么類型, 唯一能確定的是讀取的類型 is instance of T), , dest 是 List super T> 類型的, 因此它可以寫入 T 類型或其子類的數據.
摘要:定義具有一個或多個類型變量的類,稱之為泛型類。泛型類的繼承創建對象的兩種方式錯誤方式錯誤原因繼承了泛型類,但并不是泛型類,所以不能這樣創建對象。同樣是泛型類,它的父類也是泛型類,它傳遞的是常量。
泛型類
public class A {
//在成員變量上使用泛型
private T t;
public A() {}
//構造參數類型上...