泛型 (Generic)
泛型 (Generic)募闲,即“參數(shù)化類型”俘陷,就是允許在定義類罗捎、接口、方法時使用類型形參拉盾,這個類型形參將在使用時(聲明變量桨菜、創(chuàng)建對象、調(diào)用方法)傳入實際的類型參數(shù)(類型實參)捉偏。
好處
泛型的好處是在編譯的時候檢查類型安全倒得,并且所有的強(qiáng)制轉(zhuǎn)換都是自動和隱式的,可以提高代碼的重用率夭禽。
規(guī)則
1. 使用簡練的名字作為類型形參的名字霞掺,最好為單個的大寫字母,比如 T 讹躯;
2. 如果一個泛型類有泛型方法菩彬,對于它們的類型形參來說缠劝,應(yīng)避免使用相同的名字;
3. 泛型的類型實參只能是類類型骗灶,不能是基本數(shù)據(jù)類型惨恭。
“菱形”語法
在 Java 7 之前,如果使用帶泛型的接口耙旦、類定義變量時脱羡,調(diào)用構(gòu)造器創(chuàng)建對象時,構(gòu)造器后面必須帶泛型免都,如: List<String> list = new ArrayList<String>();
而從 Java 7 開始锉罐,Java 允許在構(gòu)造器后面不帶完整的泛型信息,只需給出一對尖括號即可<>琴昆,如:List<String> list = new ArrayList<>();
定義泛型類
具體例子:
Person - class
上面定義了一個帶泛型聲明的 Person<T> 類氓鄙,其有一個形式參數(shù)為泛型的構(gòu)造器和一個返回值類型為泛型的 getInfo() 方法,使用 Person<T> 類時就可以為 T 類型形參傳入實際的類型參數(shù)业舍。
運(yùn)行結(jié)果:
Result
結(jié)果分析:
第27行代碼的返回結(jié)果為 true,這是因為不管為泛型的類型形參傳入什么類型實參升酣,它們依然被當(dāng)成同一個類處理舷暮,在內(nèi)存中也只占一塊內(nèi)存空間。因此噩茄,在靜態(tài)變量下面、靜態(tài)方法、靜態(tài)初始化塊的聲明和初始化中均不能使用類型形參绩聘。另外沥割,instanceof 運(yùn)算符后也不能使用泛型類。
定義泛型接口
定義泛型接口與定義泛型類道理相同凿菩。
定義泛型方法 (Generic Method)
1. 泛型方法机杜,即在聲明方法時定義一個或多個類型形參;
2. 語法格式為:
修飾符 <T, S> 返回值類型 方法名 (參數(shù)列表) {}
3. 泛型方法中定義的類型形參只能在該方法里使用衅谷。
類型通配符
1. 類型通配符是一個問號 ? 椒拗, 將問號作為類型實參傳給泛型類或泛型接口,如:List<?> (意思是元素類型未知的 List)
2. 在 Java 的集合框架中获黔,對于參數(shù)值是未知類型的容器類蚀苛,只能讀取其中元素,不能向其中添加元素玷氏,因為編譯器無法確定添加的元素的類型和集合中的類型是否兼容堵未,但 null 例外,因為它是所有引用類型的實例盏触。
設(shè)定類型通配符的上限
1. 當(dāng)使用 List<?> 這種形式時渗蟹,表明這個 List 集合可以是任何泛型 List 的父類块饺,如果我們只希望這個 List 集合代表某一類型的父類,可以考慮設(shè)定類型通配符的上限拙徽。
2. 設(shè)定類型通配符上限的格式為:List<? extends Xxxx>
注:Xxxx表示一個類刨沦,此處的 ? 表示未知類型,但是此處的未知類型一定是 Xxxx 的子類或它本身膘怕,Xxxx 稱為這個通配符的上限(upper bound).
3. 由于編譯器無法確定這個受限制的通配符的具體類型想诅,所以不能把 Xxxx 對象及其子類的對象加入到這個泛型集合中,只能讀取岛心。
設(shè)定類型通配符的下限
設(shè)定類型通配符上限的格式為:List<? super Xxxx>
注:Xxxx表示一個類来破,此處的 ? 表示未知類型,但是此處的未知類型一定是 Xxxx 的父類或它本身忘古,Xxxx 稱為這個通配符的下限(lower bound).
設(shè)定類型形參的上限
1. 同設(shè)定類型通配符的上限一樣徘禁,Java運(yùn)行設(shè)定類型形參的上限,用于表示傳給該類型形參的實際類型是該上限類型或其子類髓堪,如:
public void drawAll(List<? extends Shape> shapes){}
注:問號 ? 表示 Shape 的未知子類送朱,編譯器無法確定這個類型是什么,所以無法把任何對象添加到這種集合中
2. 當(dāng)為需要類型形參設(shè)定多個上限時干旁,類上限必須位于第一位驶沼,并且最多只有一個,而接口上限數(shù)量則沒有限制争群,如:
public class Student<? extends Person & Serializable>{}
參考資料: