1. 程式人生 > 其它 >java 定義list_Java基礎:Java語法糖3之泛型

java 定義list_Java基礎:Java語法糖3之泛型

技術標籤:java 定義list

泛型初探

在泛型(Generic type或Generics)出現之前,是這麼寫程式碼的:

public static void main(String[] args){ List list = new ArrayList(); list.add("123"); list.add("456");  System.out.println((String)list.get(0));}

當然這是完全允許的,因為List裡面的內容是Object型別的,自然任何物件型別都可以放入、都可以取出,但是這麼寫會有兩個問題:

1、當一個物件放入集合時,集合不會記住此物件的型別,當再次從集合中取出此物件時,該物件的編譯型別變成了Object

2、執行時需要人為地強制轉換型別到具體目標,實際的程式絕不會這麼簡單,一個不小心就會出現java.lang.ClassCastException,即型別轉換異常

所以,泛型出現之後,上面的程式碼就改成了大家都熟知的寫法:

public static void main(String[] args){ List list = new ArrayList(); list.add("123"); list.add("456");  System.out.println(list.get(0));}

這就是泛型。泛型是對Java語言型別系統的一種擴充套件,有點類似於C++的模板,可以把型別引數看作是使用引數化型別時指定的型別的一個佔位符。引入泛型,是對Java語言一個較大的功能增強,帶來了很多的好處:

1、型別安全。型別錯誤現在在編譯期間就被捕獲到了,而不是在執行時當作java.lang.ClassCastException展示出來,將型別檢查從執行時挪到編譯時有助於開發者更容易找到錯誤,並提高程式的可靠性

2、消除了程式碼中許多的強制型別轉換,增強了程式碼的可讀性

3、為較大的優化帶來了可能

getClass()相同

看一段程式碼:

public static void main(String[] args){ List stringList = new ArrayList(); List integerList = new ArrayList(); System.out.println(stringList.getClass() == integerList.getClass());}

執行結果為:

true

這意味著,泛型是什麼並不會對一個物件例項是什麼型別的造成影響,所以,通過改變泛型的方式試圖定義不同的過載方法也是不可以的:

8a7a8186ebeda64efb7fae93b458c372.png

儘量使用精確的型別定義泛型

儘量使用精確的型別定義泛型,除非必要,否則不要寫一個介面或者父類上去:

public static void main(String[] args){ List list = new ArrayList(); list.add(4); list.add(2.2); for (Number number : list) System.out.println(number);}

就像這樣,list中的是一個Number型別,往裡面新增的是Integer與Double,這樣導致get出來的元素也都是Number型別的,失去了子類擴充套件的功能。如果要讓子類變為Interger和Double也可以,(Integer)list.get(0)和(Double)list.get(1)強轉就可以了,但是這樣不就失去了泛型的意義了嗎?所以,儘量用精確的型別去定義泛型。

使用型別萬用字元

List不是List的父型別,List不是List的父型別,試圖用以下方式賦值是不允許的:

1 public static void main(String[] args)2 {3 List numberList = new ArrayList();4 List integerList = new ArrayList();5 numberList = integerList;6 }

第5行將報錯"Type mismatch: cannot convert from List to List"。有人可能覺得這樣很不方便:我在一個方法裡面只需要迴圈檢索一個List,也不能利用多型放一個父型別進去,也不能過載,那怎麼辦呢?針對這個問題,Java給開發者提供了萬用字元"?",看一下:

public static void main(String[] args){ List stringList = new ArrayList(); List integerList = new ArrayList();  printList(stringList); printList(integerList);} private static void printList(List> l){ for (Object o : l) System.out.println(o);}

>是型別萬用字元,表示是任何泛型的父型別,這樣List、List這些都可以傳遞進入printList方法中,注意這裡的引數不能寫成List,這樣就報錯了,E未定義。當然>也可以不加,不過這樣會有警告:如果傳遞一個List給List,相當於傳遞一個只承諾將它當作List(原始型別)的方法,這將會破壞使用泛型的型別安全。

再注意一點,使用型別萬用字元,只能從中檢索元素,不能新增元素

泛型方法

public static void main(String[] args){ System.out.println(ifThenElse(false, "111