1. 程式人生 > >Java必知---泛型(下)

Java必知---泛型(下)

參考:Java必知—泛型(下) 本文將會講到的是泛型的進階知識:萬用字元、PECS原則和型別擦除。 1.型別萬用字元

型別萬用字元:額...說白了就是一個?。

2.PECS原則 PECS全文為“Producer Extends, Consumer Super”,意思是作為作為生產者時使用extends,作為消費者時使用super。 啥玩意兒???聽不懂 沒關係 來看下面的例子:

List<? extends Ineteger> fe = new ArrayList();      
List<? super Ineteger> fs=new ArrayList();

//The method add(capture#5-of ? extends Object) in the type List<capture#5-of ? extends Object> is not applicable for the arguments (String)
//生產者操作 fe.add(1); fs.add(1); //消費者操作 for (Integer s : fe) { } for (Integer s : fs) { }

可以看出,fe.add()作為生產者的動作往集合中新增String型別的資料時,編譯器會報錯:因為java中不允許不確定的型別加入集合,作為Integer的子類,此時編譯器並不知道fe被add進去的具體是什麼子型別,因此就會報錯(因為子類可能有著和父類不一樣的形態,如果不限定規則,隨便往裡新增各種不同的子類,那在讀取list裡的內容時,就會出錯,因為Java乾脆把規則限定在前面)。而在進行消費者的操作時,fs在遍歷資料時,由於資料型別為Integer或者Integer的父類,因此,

<?>

因為PECS最大的原則就是無論是生產操作還是消費操作,必須讓編譯器知道具體操作的型別是什麼,否則不好意思,不給過!! 由上面的例子我們可以整理出一下規則:

1.如果要從集合中讀取型別T的資料,並且不能寫入,可以使用 ? extends 萬用字元;(Producer Extends) 2.如果要從集合中寫入型別T的資料,並且不需要讀取,可以使用 ? super 萬用字元;(Consumer Super) 3.如果既要存又要取,那麼就不要使用任何萬用字元

3.型別擦除: JDK1.5引入了泛型,旨在減少型別強制轉換的操作,加強引數型別的安全,但是泛型的作用域在編譯階段,編譯完成之後,所有泛型引數型別都會被清除,這就是型別擦除。 下面來看一段程式碼:

List<String> listString=new ArrayList();
List<Integer> listInteger=new ArrayList();

System.out.println(listString.getClass());
//輸出:class java.util.ArrayList

System.out.println(listInteger.getClass());
//輸出:class java.util.ArrayList

System.out.println(listInteger.equals(listString));
//輸出:true

上面的程式碼得出以下結論:listString、listInteger並不是ArrayList的子類,它們都是ArrayList 由此可見,泛型的存在只是在編譯階段,在執行階段它們的型別已經被擦除,而泛型也不存在父類子類這種說法。