---
# System prepended metadata

title: Generic
tags: [Java]

---

# Generic

## introduction
假設我們有:
```java=
class IntegerCoordinate {
    public Integer x;
    public Integer y;
    
    public IntegerCoordinate(Integer x,Integer y) {
        this.x = x;
        this.y = y;
    }
}
class FloatCoordinate {
    public Float x;
    public Float y;
    
    public FloatCoordinate(Float x,Float y) {
        this.x = x;
        this.y = y;
    }
}
```
假設我們兩個class的成員幾乎相似,但只有物件Type不同
我們可以寫成
```java=
class Coordinate {
    public Object x;
    public Object y;
    
    public Coordinate(Object x,Object y) {
        this.x = x;
        this.y = y;
    }
}
```
並且使用:
```java=
public class Main {
    public static void main(String[] args) {
        Coordinate c = new Coordinate(10,20);
        Integer i = (Integer) c.x;
    }
}
```
但假設你記錯了呢? 你放入的是浮點數
```java=
public class Main {
    public static void main(String[] args) {
        Coordinate c = new Coordinate(10.5,20.5);
        Integer i = (Integer) c.x; //出錯
    }
}
```

## implementation
所以我們可以把
```java=
class Coordinate {
    public Object x;
    public Object y;
    
    public Coordinate(Object x,Object y) {
        this.x = x;
        this.y = y;
    }
}
```
內的"Object" 全部改成一個自訂的名稱,通常叫做T (Type)
並且在className後面寫```<T>```來表示T是我們的泛型代號
如果有多個,可以用<T,T2,T3...>表示

Key,Value通常使用<K,V>
Element通常使用<E>
```java=
class Coordinate<T> {
    private T x;
    private T y;

    public Coordinate(T x,T y) {
        this.x = x;
        this.y = y;
    }
    
    public T getX() {
        return x;
    }
    
    public void setX(T x) {
        this.x = x;
    }
    
    public T getY() {
        return y;
    }
    
    public void setY(T y) {
        this.y = y;
    }
}
```
使用時,把後面的```T```取代成你要的Type(不能是primitive)
```java=
public static void main(String[] args) {
    Coordinate<Integer> c = new Coordinate<>(10,20);
    c.setX(30);
    Integer i = c.getX(); //30
}
```

如果想要限定某泛型只能是某類別的子類別
可以寫說```T extends AnotherClass```
像是
```java=
class Test<T extends Anotherclass> {
    //...
}
```
還有另一種是界定父類別的:
```java=
class Test<T super Anotherclass> {
    //...
}
```
    
Static Method:
```java=
public static <T> void aStaticMethod(T t) {
    System.out.println(t.getClass().getName() +" "+t);
}
```
    
## Wildcard
```<?>```可以用來表示任意泛型
但是這代表不確定這個泛型的類別
如果對她進行某特定類別操作 會無法編譯

像這裡, 我不知道Coordinate<E>的E是什麼類別,所以我打個``?``
但是底下又用了Integer
```java=
Coordinate<?> c = new Coordinate<>(10,20);
c.setX(30); //error
Integer i = c.getX(); //error
```
以下範例就沒問題:
```java=
public static void main(String[] args) {
    Coordinate<?> c = new Coordinate<>(10,20);
    printCoordinate(c);

    Coordinate<Double> c2 = new Coordinate<>(30.5,40.5);
    printCoordinate(c2);
}


public static <T> void printCoordinate(Coordinate<?> t) {
    System.out.println(t.getX()+" "+t.getY());
}
```