一、最基本的泛型使用
二、限制可使用的類型
目的 : 可以限制使用時,只能某個特定型態或其子類別來實例化。
key : 使用 extends 指定型態
三、WildCard指定
說明 :
如上例 Egg<Integer> 並非是 Egg類型,而是Egg<Integer>的類型
Egg<Integer> e1 = null;
Egg<Boolean> e2 = null;
e1和e2不能相互參考,因為兩個是不同類型,e1是Egg<Integer>,而e2是<Boolean>
目的: 一個變數可以參考多個泛型實例
key : 利用 ? 作限定
在針對一個方法,限定只能傳進的類別,用 ? 來作限定是很實用的
上面的寫法,表示Egg<ArrayList>可以傳入,Egg<LinkedList>也可以傳入
如果不希望任何的型態都能傳入,可以改成上面的寫法,表示只有ArrayList 及其子類才能傳入。
extends表示向下限定,也可以利用super來向上限定
宣告時,使用?而不是使用extends 或是super,表示允許Object及其下的子類,也就是所有Java物件
使用Egg<?> e1宣告和Egg e1不同的地方在於,前者無法對他再加入資訊
其實原因很簡單,Egg<ArrayList>表示實際的物件是ArrayList,因為?表示不知道實際的物件是什麼(),
如何確定加入的物件資訊,當然也就沒有理由加入新的資訊。
| public class Egg<T> { private T myObj; public T getMyObj() { return myObj; } public void setMyObj( T myObj ) { this.myObj = myObj; } } |
| public class GenericDemo { public static void main( String[] args ) { Egg<Integer> e1 = new Egg<Integer>(); e1.setMyObj( new Integer(10) ); Egg<Boolean> e2 = new Egg<Boolean>(); e2.setMyObj( new Boolean( true ) ); // 取出來就不用轉型 Integer i = e1.getMyObj(); Boolean b = e2.getMyObj(); } } |
二、限制可使用的類型
目的 : 可以限制使用時,只能某個特定型態或其子類別來實例化。
key : 使用 extends 指定型態
| import java.util.List; public class Egg<T extends List> { private T myObj; public T getMyObj() { return myObj; } public void setMyObj( T myObj ) { this.myObj = myObj; } } |
| import java.util.ArrayList; import java.util.LinkedList; public class GenericDemo { public static void main( String[] args ) { // 只有List介面的子類才能使用 Egg<ArrayList> e1 = new Egg<ArrayList>(); e1.setMyObj( new ArrayList() ); Egg<LinkedList> e2 = new Egg<LinkedList>(); e2.setMyObj( new LinkedList() ); ArrayList i = e1.getMyObj(); LinkedList b = e2.getMyObj(); // 下面這段就無法通過編譯 Egg<HashMap> e3 = new Egg<HashMap>(); } } |
三、WildCard指定
說明 :
如上例 Egg<Integer> 並非是 Egg類型,而是Egg<Integer>的類型
Egg<Integer> e1 = null;
Egg<Boolean> e2 = null;
e1和e2不能相互參考,因為兩個是不同類型,e1是Egg<Integer>,而e2是<Boolean>
目的: 一個變數可以參考多個泛型實例
key : 利用 ? 作限定
public class Egg<T> { private T myObj; public T getMyObj() { return myObj; } public void setMyObj( T myObj ) { this.myObj = myObj; } } |
| import java.util.*; public class GenericDemo { public static void main( String[] args ) { Egg<? extends List> e1 = null; // 只要是List的子類都可使用 e1 = new Egg<ArrayList>(); e1 = new Egg<LinkedList>(); // 下面這段在編輯時會錯誤,因為HashMap並非List的子類 e1 = new Egg<HashMap>(); } } |
在針對一個方法,限定只能傳進的類別,用 ? 來作限定是很實用的
| public class Egg<T extends List> { private T myObj; public T getMyObj() { return myObj; } public void setMyObj( T myObj ) { this.myObj = myObj; } public void print( Egg e ) { System.out.println( e ); } } |
| // 只有 ArrayList及其子類才能傳入 public void print( Egg<? extends ArrayList> e ) { System.out.println( e ); } |
extends表示向下限定,也可以利用super來向上限定
| // 只有 ArrayList及其父類才能傳入 public void print( Egg<? super ArrayList> e ) { System.out.println( e ); } public static void main( String[] args ) { Egg<? super ArrayList> e1 = null; // 只要是ArrayList或ArrayList的父類都可使用 e1 = new Egg<ArrayList>(); // 下面這段在編輯時會錯誤,因為LinkedList並非ArrayList的子類 e1 = new Egg<LinkedList>(); } |
宣告時,使用?而不是使用extends 或是super,表示允許Object及其下的子類,也就是所有Java物件
使用Egg<?> e1宣告和Egg e1不同的地方在於,前者無法對他再加入資訊
| import java.util.*; public class GenericDemo { public static void main( String[] args ) { Egg<ArrayList> e1 = new Egg<ArrayList>(); e1.setMyObj( new ArrayList() ); Egg<?> e = e1; // 可取得資訊 System.out.println( e.getMyObj() ); // 可移除資訊 e.setMyObj( null ); System.out.println( e.getMyObj() ); // 但是不能重新加入資訊,下面這行無法通過編譯 e.setMyObj( new ArrayList() ); } } |
其實原因很簡單,Egg<ArrayList>表示實際的物件是ArrayList,因為?表示不知道實際的物件是什麼(),
如何確定加入的物件資訊,當然也就沒有理由加入新的資訊。
