之前有接觸過泛型也有了解過今天再次看了一下還是有很多收穫的。我個人大致做一下總結:
1.泛型本質其實就是參數化類型或者說是類型參數。泛型作爲參數和我們方法的實際類型參數的區別就是它是形式類型參數,也就是說它只是泛指我們的類型參數,而不是說具體的某一個類型。爲什麼需要泛型呢?
List list=new ArrayList<>(); list.add("aa");//添加一個字符串 list.add(2); //使用泛型 List<String> list2=new ArrayList<String>(); list2.add("ddd"); //The method add(int, String) in the type List<String> //is not applicable for the arguments (int //list2.add(3); //這裏就報錯了 也就是不能往集合中添加任何非String類型的對象 Object object=list.get(0); //沒有泛型jvm不知道存儲的類型所以獲得的就是Object類型 String string=list2.get(0); //通過泛型聲明JVM知道我們此集合中 //存儲的都是String類型所以不需要做任何處理或者是轉換 1,類型安全。 泛型的主要目標是提高 Java 程序的類型安全。通過知道使用泛型定義的變量的類型限制, 編譯器可以在一個高得多的程度上驗證類型假設。沒有泛型,這些假設就只存在於程序員的頭腦中 (或者如果幸運的話,還存在於代碼註釋中)。 2,消除強制類型轉換。 泛型的一個附帶好處是,消除源代碼中的許多強制類型轉換。這使得代碼更加可讀, 並且減少了出錯機會。 3,潛在的性能收益。 泛型爲較大的優化帶來可能。在泛型的初始實現中,編譯器將強制類型轉換(沒有泛型的話, 程序員會指定這些強制類型轉換)插入生成的字節碼中。但是更多類型信息可用於編譯器這一事實, 爲未來版本的 JVM 的優化帶來可能。由於泛型的實現方式,支持泛型(幾乎)不需要 JVM 或類文件更改。 所有工作都在編譯器中完成,編譯器生成類似於沒有泛型(和強制類型轉換)時所寫的代碼, 只是更能確保類型安全而已。
2.泛型的聲明主要有一下幾種,<T> (泛型一般用大寫字幕來表示用<>括號來聲明這裏是泛型)<?> 、<? extends Animal> 、<? super Animal>(這是爲了方便理解Animal是Cat 和Dog的父類)
3.泛型主要用在創建類型參數的類、方法和接口中。
1)創建帶有泛型的類:
注意泛型聲明的位置是在類名之後的
package me;
public class GeneTest<T> {
private T date;
public T getDate() {
return date;
}
public void setDate(T date) {
this.date = date;
}
}
2)創建帶有泛型的方法:
注意聲明泛型的位置是在修飾符之後,返回值之前的。
public <T> Class getType(T t){
return t.getClass();
}
3)創建帶有泛型的接口:
注意泛型聲明的位置是在接口名之後的
public interface Service<T>{
public void get(T t);
}
4.那麼我們如何來對帶有類型參數的對象賦值呢?首先我們來看一段代碼: //這是是創建了一個帶類型參數的鏈表
List<Animal> list=new ArrayList<Animal>();
List<Cat> list2=new ArrayList<Cat>();
//cannot convert from List<Cat> to List<Animal>
list=list2;
爲什麼list=list2會報錯呢?雖然Animal是Cat的父類但是List<Animal>卻不是List<Cat>的父類所以不能這樣賦值,這樣會破壞數據的完整性。
5.接下來說一說通配符
無限通配符<?>
上限通配符<? extends Animal>
下限通配符<? super Animal>
爲什麼要使用通配符呢?通配符的作用就是不確定類型或者說容器中存放的不是一種類型時使用的。
但是值得一提的是:在Java集合框架中,對於參數值是未知類型的容器類,只能讀取其中元素,不能像其中添加元素, 因爲,其類型是未知,所以編譯器無法識別添加元素的類型和容器的類型是否兼容,唯一的例外是null
所以List<?>和List<? extends Animal>是不能往裏面添加元素的。而List<? super Animal>是可以的。那這是爲什麼呢?接下來說說我個人的理解:
1)首先List<?>通配符?是匹配任何類型,則其參數類型一定不確定,所以這裏的List<?>是肯定不能添加任何元素的。
那爲什麼List<? extends Animal>容器也不能添加任何元素?
2)<? extends Animal>是上限通配符意思就是此參數類型可以是Animal或者Animal的任何子類。接下來看一個代碼幫助理解:
public void add(List<? extends Animal> list){
list.add(new Cat("a", 12));
list.add(new Dog("a",24));
}
//調用方法
add(new ArrayList<Cat>);
這段代碼編譯是不通過的。那麼此時爲什麼報錯?顯而易見我傳過來的參數new ArrayList<Cat>只能存儲貓類不能存儲Dog類。也就是說List<? extends Animal>容器不能存儲Animal的
所有子元素
所以List<? extends Animal>也不能添加元素。除了nul值。3)而List<? super Animal>是可以添加元素的。<? super Animal>是下限通配符。此參數類型可以是Animal和其所有父類
public void add(List<? super Animal> list){
list.add(new Cat("a", 12));
list.add(new Dog("a",24));
}
//調用方法
add(new ArrayList<Animal>); 此時容器可以存儲Animal的所有子類元素,是一個參數類型確定的容器。