通俗易懂的理解java泛型

泛型是JAVA 1.5版本之後引入的一個新特性,它允許在定義類、接口和方法的時候使用類型參數,這些類型參數將在使用時確定。泛型的引入,使得JAVA具有了更好的代碼複用性,更好的類型安全性,更好的可讀性。泛型的引入,使得JAVA具有了更好的代碼複用性,更好的類型安全性,更好的可讀性。

JAVA泛型的本質是參數化類型,也就是說所操作的數據類型被指定爲一個參數。這種參數類型可以用在類、接口和方法的創建中,分別稱爲泛型類、泛型接口、泛型方法。

JAVA泛型的好處:

  1. 代碼複用性:泛型類、泛型接口、泛型方法的代碼可以被重用,不用重複編寫相同的代碼。
  2. 類型安全:泛型可以在編譯時期進行類型檢查,保證類型安全。
  3. 可讀性:泛型可以減少強制類型轉換的代碼,提高代碼的可讀性。

以動物界爲例解釋多態和泛型

什麼是多態

多態就是同一種事物的多種形態,比如動物,狗,鳥,他們都是動物,但是他們的運動方式不同,這就是多態
不同的動物的運動方式不同,比如狗的運動方式是跑,鳥的運動方式是飛,那麼我們可以定義一個動物類,然後定義一個狗類和鳥類,他們同屬於動物,卻又有不同的運動方法,這就實現了多態

什麼是泛型

雖然同屬於動物界,但是動物們的繁衍行爲生下的後代也不相同 ,比如狗生下的後代是狗,鳥生下的後代是鳥 ,如果我們用一個類來表示動物,且定義一個繁衍行爲返回後代

1
2
3
4
5
public class Animal {
public Animal breed(){
return new Animal();
}
}

如果我希望對某個具體的動物進行描述,就只能繼承動物類,然後重寫breed方法,比如狗類

1
2
3
4
5
6
public class Dog extends Animal{
@Override
public Dog breed(){
return new Dog();
}
}

那有沒有一種方式 可以在我指定的動物是狗的時候 直接生出一隻狗狗呢?這就需要用到泛型了

我們可以定義一個佔位符 T ,然後在breed方法中返回一個T類型的對象

1
2
3
4
5
public class Animal<T> {
public T breed(){
return new T();
}
}

使用的時候 只需要替換T爲Dog 就可以了,這樣當我需要獲取狗的後代的時候,我就可以這樣寫

1
2
Animal<Dog> dog = new Animal<>();
Dog dog1 = dog.breed();

這個T 可以是任何類型,比如狗,鳥,貓, 此時Animal 就是一個泛型類,可以用來描述任何動物,而不用每次都去繼承一個動物類,然後重寫breed方法,這樣就可以大大的減少代碼量,提高代碼的複用性

類型安全

如果說現在很多園區,每個園區都需要放入對應的動物,獅子區不能放入兔子,不然獅子就會喫掉兔子,那麼我們就可以定義一個園區類,然後定義一個放入動物的方法,這個方法的參數就是一個泛型類

1
2
3
4
5
6
public class Zoo<T extends Animal> {
public void put(T animal){
System.out.println("放入了一個"+animal.getClass().getSimpleName());
}
}

這樣就可以保證放入的動物是對應的,這樣就可以保證類型安全

放入兔子

1
2
Zoo<Rabbit> rabbitZoo = new Zoo<>();
rabbitZoo.put(new Rabbit());

放入獅子

1
2
Zoo<Lion> lionZoo = new Zoo<>();
lionZoo.put(new Lion());

如果放入了一個錯誤對象,比如放入了一隻狗,編譯器就會報錯

1
2
Zoo<Lion> lionZoo = new Zoo<>();
lionZoo.put(new Dog());

泛型的使用細節

類型實參不能是基本數據類型,比如int,boolean,但是可以是他們的包裝類,比如Integer,Boolean

1
2
Zoo<Integer> integerZoo = new Zoo<>();
integerZoo.put(new Integer(1));

靜態方法不能使用泛型類中定義的泛型,因爲靜態方法優先於對象存在,所以靜態方法中不能使用類中定義的泛型

1
2
3
4
5
6
public class Zoo<T extends Animal> {
public static void put(T animal){ //這裏會出現錯誤,因爲靜態方法不能使用泛型類中定義的泛型

System.out.println("放入了一個"+animal.getClass().getSimpleName());
}
}

修飾符與返回值類型中間的 泛型標識符 <T,E,…>,是 泛型方法的標誌

1
2
3
4
5
6
7
8
9
10
11
public class Zoo<T extends Animal> {
public void put(T animal){
System.out.println("放入了一個"+animal.getClass().getSimpleName());
}
public <T> void put2(T animal){ //這裏的T和泛型類中的T沒有任何關係,這裏的T是一個新的類型,也可以寫成B ,C ,D等等 但是需要再修飾符後面聲明
System.out.println("放入了一個"+animal.getClass().getSimpleName());
}
public <T,B,C,D,E> void put2(T animal,B b,C c,D d){ //這裏的T和泛型類中的T沒有任何關係,這裏的T是一個新的類型,也可以寫成B ,C ,D等等 但是需要再修飾符後面聲明
//....
}
}

泛型中的extends 和 super

extends 表示上界,只能是指定類型或者指定類型的子類
super 表示下界,只能是指定類型或者指定類型的父類

1
2
3
4
5
public class Zoo<T extends Animal> {
public void put(T animal){
System.out.println("放入了一個"+animal.getClass().getSimpleName());
}
}

這裏的T 只能是Animal或者Animal的子類,如果我想要放入Animal的父類,比如Object,就需要使用super

1
2
3
4
5
public class Zoo<T super Animal> {
public void put(T animal){
System.out.println("放入了一個"+animal.getClass().getSimpleName());
}
}

這裏的T 只能是Animal或者Animal的父類,如果我想要放入Animal的子類,比如Dog,就需要使用extends

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章