Java泛型
一 定義
泛型是Java SE 1.5的新特性,泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。這種參數類型可以用在類、接口和方法的創建中,分別稱為泛型類、泛型接口、泛型方法。
二 泛型作用
1)提高的代碼的復用性
2)泛型提供了類型檢查,減少了數據的類型轉換
3)保證了類型安全
例如下面這段代碼,會拋出ClassCastException異常
List list = new ArrayList(); list.add("abc"); list.add(new Integer(1));//可以通過編譯 for (Object object : list) { System.out.println((String)object);//拋出ClassCastException異常 }
使用泛型后則避免這種情況發生
List<String> list = new ArrayList<String>(); list.add("abc"); //list.add(new Integer(1));//編譯器類型檢查,不能通過編譯 for (String string : list) { System.out.println(string);//無需強制類型轉換 }
注意,不能在泛型中添加其它類型
public static <T> void fromArrayToCollection(T[] a,Collection<T> c){ for (T t : a) { c.add(t); //c.add(new Object()); //編譯錯誤 } }
三 泛型邊界
作用:
1)確保泛型類型只能是某一部分類型,比如操作數據的時候,你會希望是Number或其子類類型
2)可以調用該類型方法,Java為了兼容前面的版本,泛型的實現是通過類型擦除來實現的,使用泛型的時候加上的類型參數,會被編譯器在編譯的時候去掉,在生成的Java字節代碼中是不包含泛型中的類型信息的。這個過程就稱為類型擦除。如在代碼中定義的List<Object>和List<String>等類型,在編譯之后都會變成List。System.out.println(new ArrayList<String>().getClass()==new ArrayList<Integer>().getClass());//true
對于如下方法,如果傳入一個String,想在test方法中里面調用String.equals方法則無法實現
public void test(T t){ t.equals("");//error }
加入邊界后,則可以:
class Hasf{ public void f(); } public <T extends Hasf> void test(T t){ t.f(); }
注意:邊界也可以有多個,用class D <T extends A&B&C>{} 限制范圍中最多有一個類。如果用一個類作為限定,它必須是限定列表中的第一個。
四 泛型繼承
看如下方法
public void test(List<Object> list);
如果傳入一個List<String>,則編譯會出錯。盡管String是Object的子類,但List<String>不是List<Object>的子類,也就是說,無論類A與類B是否存在關聯,MyClass<A>與MyClass<B>都沒有任何關聯。
但因為List<E> extends Collection<E>,
所以List<Object>則是Collection<Object>的子類型,ArrayList<Object>就是List<Object>的子類型,所以test中可以傳入ArrayList<Object>
五 通配符
在聲明泛型(給泛型賦值)時,既可以指定一個具體的類型,如List<String>就聲明了具體的類型是String;也可以用通配符?來表示未知類型,如List<?>就聲明了List中包含的元素類型是未知的。?號解決java泛型中List<String> 不是List<Object>子類的問題
public static void doTest(List<Parent>list){} public static void doTest1(List<? extends Parent> list){ //不能為list添加非null數據 } class Parent{} class Child extends Parent{ } public static void main(String[] args){ List <Parent>parentList=new ArrayList<Parent>(); List <Child>childList=new ArrayList<Child>(); doTest1(parentList); doTest1(childList); // 如果是doTest(childList);的話,這里編譯錯誤 }