2009-05-27 123 views
36

我有一個關於泛型的Java問題。我聲明瞭一個通用的清單:列表<?擴展MyType>

List<? extends MyType> listOfMyType; 

然後在一些方法我嘗試實例化和項目添加到這個列表:

listOfMyType = new ArrayList<MyType>(); 
listOfMyType.add(myTypeInstance); 

哪裏myTypeInstance只是MyType類型的對象;它不會編譯。它說:

Add方法(?捕獲#3的擴展 的MyType)在類型列表中<捕獲#3的 ?擴展MyType>不適用 爲參數(MyType)

任何想法?

回答

29

你不能做延伸的「放」。看看Generics - Get and Put rule

+9

作爲喬希布洛赫說:「記住佩奇:生產者延伸消費者中超。」由於listOfMyType是一個消費者(你添加到它),`super`是有效的,`extends`不是。 – 2009-05-27 21:34:28

+0

現在鏈接已損壞。 – 2011-07-01 00:47:32

4

你不應該需要使用通配符捕捉語法在你的情況下,簡單地宣佈

List<MyType> listOfMytype; 

應該夠了。如果你想知道爲什麼,Java Generics Tutorial比你想知道Java泛型的深奧瘋狂更多。第20頁解決您的具體情況。

至於爲什麼添加通配符捕獲不起作用,這是因爲編譯器無法確定每種情況下MyType的子類是哪個列表,因此編譯器會發出錯誤。

22

考慮:

class MySubType extends MyType { 
} 

List<MySubType> subtypeList = new ArrayList<MySubType>(); 
List<? extends MyType> list = subtypeList; 
list.add(new MyType()); 
MySubType sub = subtypeList.get(0); 

sub現在包含一個MyType這是非常錯誤的。

2

有一個類似的線程在這裏: How can elements be added to a wildcard generic collection?

要獲得的仿製藥是如何工作的看看這個例子的想法:

List<SubFoo> sfoo = new ArrayList<SubFoo>(); 
    List<Foo> foo; 
    List<? extends Foo> tmp; 

    tmp = sfoo; 
    foo = (List<Foo>) tmp; 

的事情是,這是不適合本地/件變量,但對於函數簽名,這就是爲什麼它是屁股後退。

2

我不知道這是否會真正幫助你,但是這是我不得不同時呼籲Spring框架的一般方法,並希望也返回一個泛型列表的使用方法:

public <T> List<T> findAll(String tableName,Class<?> table) { 
    String sql = "SELECT * FROM "+ tableName ; 
    List<?> entities = getSimpleJdbcTemplate().query(sql, 
      ParameterizedBeanPropertyRowMapper.newInstance(table)); 
      return (List<T>) entities; 
} 

看來參數化需求你使用?登錄列表以接收結果,然後將列表轉換爲預期的返回類型。

蔭的仿製藥仍然眼花繚亂......