Java 泛型(Generics)


Java 泛型(Generics)

泛型就是將資料型別參數化,讓你在定義類別介面、類別、方法時不用先決定資料型別,例如 List<T> 中間的 T 指的就是泛型。在下面例子中,我想要有個 Box 能裝進各種 Animal。

首先有個 interface Animal

interface Animal {
    abstract String getName();
}

我現在 implement 下來寫了兩個品種貓跟狗

class Cat implements Animal {
    @Override
    public String getName() {
        return "Cat";
    }

    public String cute() {
        return "裝可愛";
    }
}

class Dog implements Animal {
    @Override
    public String getName() {
        return "Dog";
    }

    public String swing() {
        return "搖尾巴";
    }
}

我需要個盒子讓上面的貓貓狗狗進去盒子

public class Box<Animal> {
    private Animal animal;

    public Box(Animal animal){
        this.animal = animal;
    }

    public Animal getAnimal(){
        return animal;
    }
}

此時我想把裡面的可愛小動物拿出來我可以這麼使用

Dog dog = new Dog()
Box box = new Box(dog) //把狗狗放進去
System.out.println(box.getAnimal().swing())

但此時我們的編譯器很好心的提醒我們並沒有 swing() 這個方法

System.out.println(dog.swing())

那我這時候又想要讓小狗搖尾巴我可以

System.out.println(((Dog) box.getAnimal()).swing())

反之我想放隻小貓咪進去可以 順邊讓他裝可愛

Cat cat = new Cat()
Box box = new Box(cat)
System.out.println(((Cat) box.getAnimal()).cute())

那這樣很麻煩 每次我都要進行轉型 實在讓人煩躁

於是我們可以利用泛型這樣改 class Box

public class Box<T extends Animal> {
    private T animal;

    public Box(T animal){
        this.animal = animal;
    }
    public T getAnimal(){
        return animal;
    }
}

使用上就可以不用轉型

Cat cat = new Cat()
Box<Cat> box = new Box(cat)
System.out.println(box.getAnimal().cute())

我們可以注意到當我們 box.getAnimal() 時已經是取得型態為 Cat 的物件了因此要讓他裝可愛就很方便了

可以注意到的是角誇號內的就是我們所需的型態 如果我們沒打那 box.getAnimal() 時取出的型態會是 Animal

回頭再看

public class Box<T extends Animal> {
    private T animal;

    public Box(T animal){
        this.animal = animal;
    }
    public T getAnimal(){
        return animal;
    }
}

可以看到第一行

public class Box<T extends Animal> {

public class Box 定義了類別名稱以及他是個 class

<T extends Animal> 定義了 T 型態必須是繼承或是擴充自 Animal

如果我們改成 <T> 那這個 T 就是預設只要實作 java.lang.Object 即可

那在 Java 中 class 如果沒有特別指定繼承誰那就是繼承 java.lang.Object

最後泛型在 Java 中也可用在 mothod 定義上

// 傳入型態為 T
<T extends Animal> String getName(T animal) {
    return animal.getName();
}

// 回傳型態為 T
<T extends Animal> T newCat() {
    return (T) new Cat();
}

WRITTEN BY
Aki

熱愛寫code的開發者,專注於 Android 手機 Native App 開發,對於 IOS 也有涉略。閒暇之餘也學習 JavaScript 等前端框架