一吭敢、泛型簡介
1、目的
- 語法糖:
也稱糖衣語法缭受,指在計算機語言中添加的某種語法胁澳,這種語法對語言的功能并沒有影響,但是更方便程序員使用米者。
Java中最常用的語法糖主要有泛型韭畸、變長參數(shù)宇智、條件編譯、自動拆裝箱胰丁、內(nèi)部類等随橘。
服擬機并不支持這些語法,它們在編譯階段就被還原回了簡單的基礎(chǔ)語法結(jié)構(gòu)锦庸,這個過程成為解語法糖机蔗。
泛型的目的:
Java 泛型就是把一種語法糖,通過泛型使得在編譯階段完成一些類型轉(zhuǎn)換的工作甘萧,避免在運行時強制類型轉(zhuǎn)換而出現(xiàn) ClassCastException萝嘁,即類型轉(zhuǎn)換異常。泛型的作用:
可以把類型參數(shù)看作是使用參數(shù)化類型時指定的類型的一個占位符扬卷。
List<String> list = new ArrayList<>();
2牙言、泛型的好處
- 類型安全。類型錯誤現(xiàn)在在編譯期問就被捕獲到了怪得,而不是在運行時當(dāng)作
java.lang. Class CastException展示出來咱枉,將類型檢查從運行時挪到編譯時有助于開
發(fā)者更容易找到錯誤,并提高程序的可靠性徒恋。 - 消除了代碼中許多的強制類型轉(zhuǎn)換庞钢,增強了代碼的可讀性。
- 為較大的優(yōu)化帶來了可能因谎。
二基括、泛型的使用
1、泛型類和泛型接口
1/定義接口時指定了一個類型形參财岔,該形參名為E
public interface List<E> extends Collection<E>{
//在該接口里风皿,E可以作為類型使用
public E get (int index) {}
public void add(E e) {}
}
1/定義類時指定了一個類型形參,該形參名為E
public class ArrayList<E> extends AbstractList<E> implements List<E> {
//在該類里匠璧,E可以作為類型使用
public void set(E e) {
-------
}
}
這就是泛型的實質(zhì):允許在定義接口桐款、類時聲明類型形參,類型形參在整個接口夷恍、類體內(nèi)可當(dāng)成類型使用魔眨,幾乎所有可使用普通類型的地方都可以使用這種類型形參
- 泛型類
定義一個容器類,存放鍵值對key-value酿雪,鍵值對的類型不確定遏暴,可以使用泛型來定義,分別指定為K和V指黎。
public class Container<K, V> {
private K key;
private V value;
public Container (K k, V V) {
key = k;
value= V;
}
public K getkey) {
return key;
}
public V getValue() {
return value;
}
public void setKey() {
this. key = key;
}
public void setvalue) {
this. value = value;
}
}
JDK1.7增加了泛型的“菱形"語法:Java允許在構(gòu)造器后不需要帶完成的泛型信息朋凉,只要給出一對尖括號(<>)即可,Java可以推斷尖括號里應(yīng)該是什么泛型信息;List<String> list = new ArrayList<>();
- 泛型類派生子類
當(dāng)創(chuàng)建了帶泛型聲明的接口醋安、父類之后杂彭,可以為該接口創(chuàng)建實現(xiàn)類墓毒,或者從該父類派生子類,需要注意:使用這些接口亲怠、父類派生子類時不能再包含類型形參所计,需要傳入具體的類型。
2团秽、泛型方法
所謂泛型方法主胧,就是在聲明方法時定義一個或多個類型形參。泛型方法的用法格式如下:
修飾符 <T徙垫,S> 返回值類型 方法名(形參列表){
方法體
}
注意:方法聲明中定義的形參只能在該方法里使用,而接口放棒、類聲明中定義的類型形參則可以在整個接口姻报、類中使用。
public <T> T fun(T t){
return t;
}
3间螟、泛型構(gòu)造器
正如泛型方法允許在方法簽名中聲明類型形參一樣吴旋,Java也允許在構(gòu)造器簽名中聲明類型形參,這樣就產(chǎn)生了所謂的泛型構(gòu)造器厢破。
和使用普通泛型方法一樣沒區(qū)別荣瑟,一種是顯式指定泛型參數(shù),另一種是隱式推斷摩泪;如果是顯式指定則以顯式指定的類型參數(shù)為準(zhǔn)笆焰,如果傳入的參數(shù)的類型和指定的類型實參不符,將會編譯報錯见坑。
//隱式
new Person(22);
//顯示
new<String> Person("Hello");
三嚷掠、類型通配符
類型通配符:顧名思義就是匹配任意類型的類型實參;
類型通配符是一個問號(荞驴?)不皆,將一個問號作為類型實參傳給List集合,寫
作:List<?>(意恩是元素類型未知的List)熊楼。這個問號(霹娄?)被成為通配符,它
的元素類型可以匹配任何類型鲫骗。
1犬耻、帶限通配符
- 上限通配符
如果想限制使用泛型類別時,只能用某個特定類型或者是其子類型才能實例化該類型時执泰,可以在定義類型時香追,使用extends 關(guān)鍵字指定這個類型必須是繼承某個類,或者實現(xiàn)某個接口坦胶,也可以是這個類或接口本身透典。
它表示集合中的所有元素都是Shape 類型或者其子類晴楔。
List<? extends Shape>
- 下限通配符
如果想限制使用泛型類別時,只能用某個特定類型或者是其父類型才能實例化該類型時峭咒,可以在定義類型時税弃,使用super關(guān)鍵字指定這個類型必須是是某個類的父類,或者是某個接口的父接口凑队,也可以是這個類或接口本身则果。
它表示集合中的所有元素都是Circle類型或者其父類。
List<? super Circle>
注意:
extends 可用于的返回類型限定漩氨,不能用于參數(shù)類型限定西壮。
super 可用于參數(shù)類型限定,不能用于返回類型限定叫惊。
List<? extends Fruit> list = new ArrayList<Apple>();
不能使用list.add方法添加元素款青;
List<? super Fruit> flist = new ArrayList<Fruit>();
不能使用list.get方法獲取元素;
2霍狰、類型擦除
Class c1=new ArrayList<Integer>().getclass();
Class c2=new ArrayList<String>().getclass();
System.out.println(c1==c2);
這個值為true
這是因為不管為泛型的類型形參傳入哪一種類型實參抡草,對于Java來說,它們依然被當(dāng)成同一類處理蔗坯,在內(nèi)存中也只占用一塊內(nèi)存空間康震。從Java泛型這一概念提出的目的來看,其只是作用于代碼編譯階段宾濒,在編譯過程中腿短,對于正確檢驗泛型結(jié)果后,會將泛型的相關(guān)信息擦出绘梦,也就是說答姥,成功編譯過后的class文件中是不包含任何泛型信息的。泛型信息不會進(jìn)入到運行時階段谚咬。
在靜態(tài)方法鹦付、靜態(tài)初始化塊或者靜態(tài)變量的聲明和初始化中不允許使用類型形參。由于系統(tǒng)中并不會真正生成泛型類择卦,所以instanceof運算符后不能使用泛型類敲长。