泛型就是將資料型別參數化,讓你在定義類別介面、類別、方法時不用先決定資料型別,例如 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();
}