一、最基本的泛型使用

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 );
    }
}
上面的寫法,表示Egg<ArrayList>可以傳入,Egg<LinkedList>也可以傳入

    // 只有 ArrayList及其子類才能傳入
    public void print( Egg<? extends ArrayList> e )
    {
        System.out.println( e );
    }
如果不希望任何的型態都能傳入,可以改成上面的寫法,表示只有ArrayList 及其子類才能傳入。

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,因為?表示不知道實際的物件是什麼(),
如何確定加入的物件資訊,當然也就沒有理由加入新的資訊。