泛型的本質是什么
什么是泛型,泛型是一種模板技術,就好比排序,所有的排序策略,核心問題是比較和交換,如果一種算法對double有效,則只要提供比較大小的規則,該算法也對String甚至任意數據類型有效,而泛型可以使得這樣的排序算法一個實現就應用到多中情形。
結合這種概念,就有了泛型集合,好比ArrayList集合的實現,無論對於什么數據類型,其算法結構都是一樣的,於是從JDK5后有了泛型集合。
泛型有什么好處
當然,有了泛型集合和泛型技術后,泛型帶來的好處就不只是代碼重用了,還包括類型安全,以及更好的可讀性。要知道下面的代碼,在編寫代碼的時候是不會報錯的,要命的是在運行的時候就會:
1 List list1 = new ArrayList();// 非泛型集合 2 list1.add("testString"); 3 list1.add(Integer.valueOf(10)); 4 for (Object s : list1) { 5 Integer num = (Integer) s; 6 // 類型不安全,會拋出異常 7 }
但是如果是泛型集合,你在編寫代碼的時候JDK就直接告訴你這里不可以這么使用了:
List<String> list2 = new ArrayList<String>(); //list2.add(1);//類型檢查,不是允許的類型無法放入集合
這就是所謂的類型安全了。這是泛型的第二個好處。
當然泛型的另外一個好處就是增強可讀性,取出數據的時候不再有完全沒有意義的強制類型轉換,因為程序員應該知道這個類型是什么。
泛型的非協變性
Java中的泛型集合不是協變的,下面的代碼你覺得可以編譯通過嗎:
List<String> list3 = new ArrayList<String>(); List<Object> list4 = list3;
看起來沒什么問題對吧,一個是Object集合,一個是String集合,完全兼容啊,事實上是不行的,如果行的話,泛型集合ArrayList的實例就可以裝入任何對象了不是嗎?
這里還有個小知識:Java的泛型支持是編譯期技術,所謂的類型擦除就是這個意思,我們后面再詳細聊。
那么這個問題怎么解決呢?需求是肯定存在的呀,比如我們有個方法定義:
public static void printElements(List<Object> objs)
這個方法希望接受任何List集合,顯然通過上面的內容,我們知道傳參數是傳不進去的。
解決的辦法很簡單,講List<Object> 換成List<?>,這個問號就是泛型語法中的任何類型的意思,上面的代碼換成這樣的語法,就可以接受任何類型了:
//方法聲明 public static void printElements(List<?> objs) //方法調用 List<String> list5 = new ArrayList<String>(); printElements(list5);
當然,?是沒有任何約束,我們也可以對接受的類型進一步約束,比如下面的方法定義:
public static void printElements(List<? extends Parent> objs)
這樣我們的方法要求集合的元素必須是Parent類的子類,比如Number可以限制為數字,別問我怎么知道Number的 (#^.^#)
當然,很多同學還見過這種的:
public static void printElements(List<? super Parent> objs)
反之,這樣限制了參數必須是List集合且集合的元素必須是Parent類的父類。(這是super在Java中的第三種用法,你知道還有哪兩種嗎?)
下次我給大家分享泛型類,靜態泛型方法,有興趣的關注我的博客喲。