1. 程式人生 > >List和List的區別(泛型)

List和List的區別(泛型)

java泛型的兩種用法:List是泛型方法,List

public interface Dao{
  List<T> getList(){};
}

List<String> getStringList(){
  return dao.getList();//dao是一個實現類例項
}

List<Integer> getIntList(){
  return dao.getList();
}

上面介面的getList方法如果定義成List

List<T> getList<T param1,T param2>

這樣可以限制返回結果的型別以及兩個引數的型別一致。
List

public Class Fruit(){}
public Class Apple extends Fruit(){}
public void test(? extends Fruit){};

test(new Fruit());
test(new Apple());
test(new String()); //這個就會報錯

這樣可以現在test方法的引數必須是Fruit或其子類。

型別引數“”和無界萬用字元“

public class ArrayList<E> extends AbstractList<E> implements List<E>,RandomAccess
Cloneable,java.o.Serializable{
...... }

ArrayList中的“E”也是型別引數。只是表示容器中元素Element的時候,習慣用“E”。換一個簡單的例子,我們自己定義一個新泛型容器叫Box。

class Box<T>{
    private T item1;
    private T item2;
}

為什麼這裡要用型別引數?因為這是一種”約束“,為了保證Box裡的item1, item2都是同一個型別T。Box,代表兩個item都是String。Box裡兩個item都是Integer。

List容器庫裡都幫我們寫好了,所以我們是不會去定義List的。
那什麼時候會出現List?有幾種情況,要麼是作為泛型類的成員欄位或成員方法的引數間接出現。還是剛才Box的例子:

class Box<T>{
    private List<T> item;
    public List<T> get(){return item;}
    public void set(List<T> t){item=t;}
}

現在Box類裡有三個地方出現了List:
成員欄位item的型別
get( )方法的返回值
set( )方法的引數

這裡寫成List為了表示和Box型別引數保持一致。
2. 宣告泛型方法
另外一種會出現List的地方是泛型方法。比如Function類的reduce是個靜態泛型方法,負責對列表裡的所有元素求和。這裡的List出現在引數,函式返回值和函式內部,也是為了保持泛型型別的一致性。

class Fuction{
    public static <T> List<T> reduce(List<T> list){
    //...do something
    }
    }
  1. 無界萬用字元
class Box<?>{
    private ? item1;
    private ? item2;
}

所以萬用字元是拿來使用定義好的泛型的。比如宣告List容器的一個例項物件。

List<?> list = new ArrayList<String>();
List<?> list = new ArrayList<String>();
list.add("hello");    //ERROR
list.add(111);    //ERROR
//argument mismatch; String cannot be converted to CAP#1
//argument mismatch; int cannot be converted to CAP#1

另外如果拿List

class Box<T>{
    private List<T> item;
    public List<T> get(){return item;}
    public void set(List<T> t){item=t;}
    //把item取出來,再放回去
    public void getSet(Box<?> box){box.set(box.get());}  //ERROR
    }

新的getSet()方法,只是把item先用get()方法讀出來,然後再用set()方法存回去。按理說不可能有問題。實際執行卻會報錯。

error: incompatible types: Object cannot be converted to CAP#1

原因和前面一樣,萬用字元box

class Box<T>{
    private List<T> item;
    public List<T> get(){return item;}
    public void set(List<T> t){item=t;}
    //helper()函式輔助getSet()方法存取元素
    public void getSet(Box<?> box){helper(box);}
    public <V> void helper(Box<V> box){box.set(box.get());}
    }
  1. 有界萬用字元