java泛型
-
理解泛型
我們來(lái)看一段代碼:
public void static main(String args[])
{
List list=new Arraylist();
list.add("String");
list.add(100);
}
public void static out(List list){
for(int i=0;i<list.size();i++)
{
String var=(String)list.get(i); //出錯(cuò) 100是正數(shù)不是String
System.out.prinln("var :"+var);
}
}
編譯通過(guò)傲隶,運(yùn)行時(shí)出錯(cuò)饺律,因?yàn)榫幾g時(shí)候List 默認(rèn)是Object 類型所以不會(huì)出錯(cuò),但是運(yùn)行時(shí)類型強(qiáng)制轉(zhuǎn)換就會(huì)出錯(cuò)跺株,那么有沒(méi)有一種方法保證編譯時(shí)讓其類型必須相同不然編譯不通過(guò)呢复濒?有那就是泛型類型脖卖。
簡(jiǎn)單來(lái)說(shuō)是為了防止當(dāng)編譯時(shí)是Object的對(duì)象,運(yùn)行時(shí)才知道具體類型的對(duì)象強(qiáng)制轉(zhuǎn)換錯(cuò)誤而用泛型來(lái)代替巧颈。
-
運(yùn)行時(shí)繞過(guò)泛型限制
public static void main(String args[]) { List<String> list = new ArrayList<String>(); Class sClass = list.getClass(); Method me; try { me = sClass.getMethod("add", Object.class); me.invoke(list, 100);//添加Integer類型數(shù)據(jù) Method method = sClass.getMethod("get", int.class); Object i = method.invoke(list, 0);//獲取list.get(0)數(shù)據(jù) System.out.println(i);//輸出 } catch (NoSuchMethodException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
從中我們可以看出畦木,泛型并不能限制運(yùn)行時(shí)的對(duì)象。
-
泛型‘砸泛?’和'E T V'
T E V都是一樣的只是不同符號(hào)也可以用A ,B, C十籍,一般T代表type, E代表集合元素唇礁,V代表Value
勾栗?是用于限制類型上下邊界
List<? extends father>
只要是father的子類都可以,當(dāng)然也可以不限制類型 比如ist<?>
。 -
泛型有上下變界
- 上邊界是
<盏筐? extends T>
必須要是T的子類 - 下邊界是
<围俘?supers T>
必須要是T的父類
- 上邊界是
-
泛型應(yīng)用
我們來(lái)看一個(gè)簡(jiǎn)單泛型應(yīng)用:
//先定義一個(gè)FatherBox接口 public interface FatherBox { void println(); int getID(); } //定義兩個(gè)FatherBox的子類 public class ChildFirstBox implements FatherBox { static int id = 0; private final int _id; public ChildFirstBox() { // TODO Auto-generated constructor stub id++; _id=id; } @Override public void println() { // TODO Auto-generated method stub System.out.println("ChildFirstBox Id:"+_id); } @Override public int getID() { // TODO Auto-generated method stub return _id; } } public class ChildSecondBox implements FatherBox { static int id = 0; private final int _id; public ChildSecondBox() { // TODO Auto-generated constructor stub id++; _id = id; } @Override public void println() { // TODO Auto-generated method stub System.out.println("ChildSecondBox ID:" + _id); } @Override public int getID() { // TODO Auto-generated method stub return _id; } } //試運(yùn)行程序 public static void main(String[] args) { ChildFirstBox tBox = new ChildFirstBox(); ChildSecondBox tBox2 = new ChildSecondBox(); List<FatherBox> as = new ArrayList<>(); as.add(tBox); as.add(tBox2); getNumChildFB(as); } public static void getNumChildFB(List<? extends FatherBox> sdf) { for (FatherBox t : sdf) { t.println(); } }
Box 對(duì)象可以接受任何FatherBox的子類對(duì)象,并正確的輸出琢融。從上面的例子中界牡,我們可以看出泛型相當(dāng)于Object,只是Object無(wú)法在編譯時(shí)指定類型漾抬,而泛型可以欢揖。
-
泛型優(yōu)點(diǎn)
-
類型安全
編譯器可以知道當(dāng)前類型,提高java程序的類型安全
-
消除強(qiáng)制類型轉(zhuǎn)化
消除源代碼中的許多強(qiáng)制類型轉(zhuǎn)換
-
提高性能
為以后jvm優(yōu)化提供了可能性
-
-
泛型注意事項(xiàng)
- 泛型的類型參數(shù)只能是類類型(包括自定義類)奋蔚,不能是簡(jiǎn)單類型她混。
- 泛型的類型參數(shù)可以有多個(gè)。
- 不能對(duì)確切的泛型類型使用instanceof操作泊碑。
- 不能創(chuàng)建一個(gè)確切的泛型類型的數(shù)組坤按。