什么是泛型桥言?為什么使用泛型?
泛型的出現(xiàn)意味著編寫的代碼可以被不同類型的對(duì)象所重用厌漂,提升了代碼的重用性。泛型的本質(zhì)是參數(shù)化類型斟珊,即將所需操作的數(shù)據(jù)類型設(shè)置為一個(gè)參數(shù)苇倡。
舉個(gè)實(shí)際中的栗子:我們需要設(shè)計(jì)一個(gè)柜子的類,柜子可以用于存放書本囤踩、食品或者衣物旨椒,但是我們?cè)谠O(shè)計(jì)階段不能確定柜子里具體要存放什么東西,那怎么來(lái)設(shè)計(jì)這樣一個(gè)通用型的柜子堵漱,這里就可以用到泛型综慎。所以,我們把存放元素的類型設(shè)計(jì)成一個(gè)參數(shù)勤庐,這個(gè)類型參數(shù)就稱之為泛型示惊。
舉個(gè)JAVA中的栗子:ArrayList<T>,List<T>好港,這個(gè)<T>就是類型參數(shù),也就是泛型米罚。為什么這么寫呢钧汹?因?yàn)槲覀冊(cè)趧?chuàng)建Arraylist或者List時(shí),無(wú)法確定里面具體存儲(chǔ)的元素的類型录择,但是我們有希望一個(gè)實(shí)例對(duì)象中存儲(chǔ)的元素的類型時(shí)一致的拔莱,這就需要泛型來(lái)實(shí)現(xiàn)操作。
int[] arr1 = new int[] {159,357,456};
//沒(méi)有用泛型隘竭,ArrayList中存儲(chǔ)的元素格式各樣塘秦,實(shí)際開發(fā)中在操作時(shí)是很容易出現(xiàn)問(wèn)題的
List list1 = new ArrayList();
list1.add(123);
list1.add("敲代碼的阿茄");
list1.add(arr1);
//使用泛型,限制ArrayList存放的元素的類型动看,就不能添加存儲(chǔ)其他類型的元素了
List<String> list2 = new ArrayList<>();
list2.add("敲");
list2.add("代");
list2.add("碼");
list2.add("的");
list2.add("阿");
list2.add("茄");
//list2.add(123);//無(wú)法添加
//list2.add(arr1);//無(wú)法添加
泛型使用的基本要求
- 異常類不能聲明為泛型嗤形。
- 泛型不能是基本數(shù)據(jù)類型,需要使用基本數(shù)據(jù)類型的泛型可以寫成其包裝類弧圆。
//List<int> list2 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
自定義泛型類
在類或接口中聲明的泛型赋兵,可以作為非靜態(tài)屬性的類型、非靜態(tài)方法的參數(shù)類型搔预、非靜態(tài)方法的返回值霹期。但是,不能在靜態(tài)方法中使用類的泛型拯田。
// 泛型類:類中定義有不確定的類型
public class Dict<T> {
String dictName;
int dictCount;
T dictT;
//泛型類下用了泛型的方法,報(bào)錯(cuò)历造,需要去掉static
//public static void get(T dictT) {
// this.dictT = dictT;
//}
//泛型類下沒(méi)用泛型的方法
public static void set() {
System.out.println("");
}
}
泛型方法和泛型類下的方法?
泛型方法:該泛型方法所在的類可以不是泛型類船庇。往直觀一點(diǎn)講吭产,方法中出現(xiàn)了泛型結(jié)構(gòu)<>。
那么鸭轮,泛型方法可以是靜態(tài)的嗎臣淤?可以,因?yàn)榉盒蛥?shù)是在調(diào)用方法時(shí)確定的,并非在實(shí)例化時(shí)確定的窃爷。
public class GenericTest {
public static void main(String[] args) {
Dict<Float> dict = new Dict<>();
dict.set1(0.0f);
//調(diào)用泛型方法邑蒋,泛型類型跟類的泛型沒(méi)關(guān)系,不受影響
dict.set2(" ");
dict.set2(36);
dict.set2(new ArrayList());
}
}
//泛型類
class Dict<T> {
String dictName;
int dictCount;
//泛型類中的方法:如果調(diào)用了泛型則不能為靜態(tài)
public void set1(T dictT) {
System.out.println("我是泛型類下的方法");
}
//泛型方法:可以為靜態(tài)
public static <T> void set2(T dictT) {
System.out.println("我是泛型方法");
}
}
泛型與繼承
- 如果類A是類B的父類按厘,但是医吊,
G<A>
不是G<B>
的父類(G是類或者接口),兩個(gè)屬于不同的類逮京。所以不存在兩者間的多態(tài)和向上轉(zhuǎn)型卿堂。 - 但是呢,
A<G>
仍然是B<G>
的父類懒棉。
通配符
通配符:?
- 利用通配符草描,創(chuàng)建二者的共同父類览绿,
G<A>
和G<B>
的共同父類G<?>
; - 但是陶珠,不能往其中添加新數(shù)據(jù),常用于賦值操作而已享钞,僅能添加
null
; - 允許讀取數(shù)據(jù)揍诽,讀取數(shù)據(jù)的類型為object;
舉例說(shuō)明:定義List<?>
是List<Object>
和List<String>
的公共父類。
//不能添加數(shù)據(jù)栗竖,除了null
List<?> list = new ArrayList<>();
//list.add(16);//報(bào)錯(cuò)
//list.add(" ");//報(bào)錯(cuò)
list.add(null);
//允許讀取數(shù)據(jù)
List<?> list = new ArrayList<>();
List<String> list1 = new ArrayList<>();
list1.add("newstring");
list =list1;
list.add(null);
Object obj = list.get(0);
System.out.println(obj);//newstring
有限制條件的通配符
-
G<? extends A>
可以作為G<A>
和G<B>
的父類暑脆,其中B是A的子類;即狐肢,可以作為所有繼承于A類的類G<A的子類>
的父類添吗。 -
G<? super A>
可以作為G<A>
和G<B>
的父類,其中B是A的父類份名;即碟联,可以作為所有A的父類的G<A的父類>
的父類。
// 下面舉例類的關(guān)系:Earth extends Sun, Sun extends Universe
List<? extends Sun> list1 = new ArrayList<>();// 可以作為L(zhǎng)ist<Sun及其子類>的父類
List<? super Sun> list2 = new ArrayList<>();// 可以作為L(zhǎng)ist<Sun及其父類>的父類
List<Universe> list3 = new ArrayList<>();
List<Sun> list4 = new ArrayList<>();
List<Earth> list5 = new ArrayList<>();
list1 = list4;// 多態(tài)
list2 = list4;//多態(tài)
// 讀取數(shù)據(jù)
Sun s1 =list1.get(0);//獲取的數(shù)據(jù)是Sun或者Sun的子類的對(duì)象僵腺,可以實(shí)現(xiàn)多態(tài)
Earth e1 =(Earth)list1.get(0);//不強(qiáng)轉(zhuǎn)會(huì)報(bào)錯(cuò)鲤孵,因?yàn)楂@取的數(shù)據(jù)可能是Sun的對(duì)象,父類轉(zhuǎn)子類需要強(qiáng)轉(zhuǎn)
Sun s2=(Sun)list2.get(0);//不強(qiáng)轉(zhuǎn)會(huì)報(bào)錯(cuò)辰如,獲取的數(shù)據(jù)可能是Sun的父類普监,父類轉(zhuǎn)子類需要強(qiáng)轉(zhuǎn)
Object o=list2.get(0);//不強(qiáng)轉(zhuǎn)情況下,只能是Object
// 寫入數(shù)據(jù)
list2.add(new Sun());//只能添加Sun本身琉兜,或者Sun的子類
//因?yàn)閘ist2存的可能是Sun及其父類凯正,假設(shè)new的是Universe,但是list2中存儲(chǔ)的是Sun,
//即實(shí)際?=Sun,那么Universe作為父類是無(wú)法直接賦給子類的
list2.add(new Earth());
//list1.add();//無(wú)法添加數(shù)據(jù)豌蟋,因?yàn)槟銦o(wú)法確定存儲(chǔ)的子類有多小