---
# System prepended metadata

title: 泛型符號
tags: [Java, Generics, 泛型]

---

# 泛型符號
在類別裡用一個「一般化(Generic)的符號」，表示未來該符號可以是任何參考型別；
常用的符號與字義有：
* T : Type
* E : Element
* K : Key
* V : Value
* R : Result

## 萬用字元「?」(wildcards)
| 語法 | 說明 |
|-|-|
| `<?>`           | 可以為任何型別，沒有上/下限。|
| `<? extends T>` | 型別必須是 T 或是 T 的**子類別**。T為上限，沒有下限 |
| `<? super T>`   | 型別必須是 T 或是 T 的**父類別**。T為下限，沒有上限 |

## 泛型裡的多型
```graphviz
digraph dfd{
    node [shape=record];
    rankdir=BT;
    classAA [label="{AA||}"];
    classA [label="{A||}"];
    classB [label="{B||}"];
    classC [label="{C||}"];
    classA -> classAA
    classB -> classA
    classC -> classA
}
```

## 泛型使用萬用字元(wildcards)注意事項
||`<?>`|`<? extends T>`|`<? super T>`|
|-|-|-|-|
|檢視成員|只能用 Object 型別檢視|使用 T 或其父類別檢視成員|只能用 Object 型別檢視|
|增加成員|無法增加成員|無法增加成員|可以增加 T 或其子類別的成員|

## 範例
### `<?>`
```java=
private static void process(List<?> list) {
    // list 可以是任意型別，所以一律無法加入元素，以避免 List<B> 加入 new C()
    // list.add(new Object()); // compile error!
    // list.add(new A());      // compile error!
    // list.add(new B());      // compile error!
    // list.add(new C());      // compile error!
    
    // 可以用 Objcet 參照
    for (Object obj : list) System.out.println(obj);
}

private void testProcess() {
    process(new ArrayList<AA>());
    process(new ArrayList<A>());
    process(new ArrayList<B>());
    process(new ArrayList<C>());
}
```
### `<? extends A>`
```java=
private void process(List<? extends A> list) {
    // list 可以是ArrayList<A>, ArrayList<B>或ArrayList<C>型別
    // 所以無法加入元素，以避免 List<B> 加入 new C()
    // list.add(new AA()); // compile error!
    // list.add(new A());  // compile error!
    // list.add(new B());  // compile error!
    // list.add(new C());  // compile error!
    
    for (A a : list) System.out.println(a.getClass().getName());
}

private void testProcess() {
    // process(new ArrayList<AA>()); // compile error!
    process(new ArrayList<A>());
    process(new ArrayList<B>());
    process(new ArrayList<C>());
}
```

### `<? super A>`
```java=
private void processElements(List<? super A> list) {
    // list.add(new AA()); // compile error!
    list.add(new A());
    list.add(new B());
    list.add(new C());
    
    // list 可以是ArrayList<AA>或ArrayList<A>
    // 所以僅可以用Object參照
    // for (A a : list) System.out.println(a); // compile error!
    for (Object obj : list) System.out.println(obj);
}

private void testProcess() {
    process(new ArrayList<AA>()); 
    process(new ArrayList<A>());
    // process(new ArrayList<B>()); // compile error!
    // process(new ArrayList<C>()); // compile error!
}
```

###### tags: `Java` `泛型` `Generics`