2012-09-06 30 views
1

此代碼爲什麼不允許使用泛型和通配符?

static void writeTo(List<? super Apple> apples) { 
     apples.add(new Apple()); 
     apples.add(new Jonathan()); 
    } 

這段代碼的作者指出,

的論點蘋果是一些類型,它是蘋果公司的基本類型的列表;因此您知道添加Apple或Apple的子類型是安全的。由於下界是蘋果,因此喬納森是蘋果的一個子類,

喬納森是蘋果的一個子類。

但當我這個

List<Jonathan> loj = new ArrayList<Jonathan>(); 
    listSuper(loj); 

它給了我這個錯誤

The method listSuper(List<? super Apple>) in the type Basket<T> is not applicable for the arguments (List<Jonathan>) 

listSuper看起來像這樣

static void listSuper (List<? super Apple> cont) {} 

如何兩者有何不同?

另外,我發佈的第一個代碼是什麼使我困惑的是我認爲的 ?超T意味着任何基類型的T,但從它的外觀來看,他添加了T的一個子類型。我很困惑。

+0

不明白這個問題。這兩個函數似乎都有相同的簽名。問題是什麼? – vainolo

+0

@vainolo我添加了一些關於錯誤的信息。請檢查一下 – KyelJmD

+1

[Producer Extends,Consumer Super](http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs/2723538#2723538) –

回答

5

List<? super Apple>意味着List您可以添加到Apple(既然JonathanApple,你可以把Jonathan s轉換一個該類型的List以及)。

它可以是List<Apple>List<Fruit>List<Object>,但不List<Jonathan>,因爲你不能把任意Apple s轉換List<Jonathan>。如您所見,在這種情況下,?可以是Apple或其任何超類。

List<? extends Apple>表示一個List你可以從中獲得一個Apple。它可以是List<Apple>List<Jonathan>,但不是List<Fruit>,因爲List<Fruit>不保證只包含Apple s。

此解釋被稱爲「生產者 - extends,消費者 - super」規則:如果參數作爲元素的消費者,則應聲明爲super,反之亦然。

+0

但是他如何在List中添加一個Jonathan對象?超級蘋果 – KyelJmD

+0

@KyelJmD:更新。 'Jonathan'是一個'Apple',因此你可以把它放到一個'List'中,它可以包含'Apple's。 – axtavt

0

該代碼的作者是錯誤的。您無法將Apple的子類傳遞給需要的方法?超級蘋果,只有蘋果本身和蘋果的超級產品。如果你想能夠添加Apple的子類,你需要使用?延伸蘋果。

+0

您錯了,請閱讀最佳答案。類型列表?超級蘋果可以採取蘋果及其所有亞型。類型列表?擴展蘋果公司根本沒有添加任何東西,但你總是從中獲得蘋果。 – Stefan

4

JonathanApple的子類型,而不是超類型。這將匹配<? extends Apple>但不匹配<? super Apple>

+0

但是他怎麼會在蘋果列表中加入Jonathan?在writeTo方法中? – KyelJmD

+0

將'Jonathan'的實例添加到'List '中是沒有問題的,爲什麼會有?這與你正在嘗試做的完全不同...... – verdesmarald

0

類型參數必須是蘋果的,不是,這是什麼Jonathan是。所以,舉例來說,這將是有效的:

List<Fruit> loj = new ArrayList<Fruit>();  
listSuper(loj); 
0

如何兩者有何不同?

另外,我發佈的第一個代碼令我困惑的是我想到 ?超T意味着T的任何基本類型,但從外觀 它增加了T的子類型。我很困惑。

您必須區分(1)您可以插入到通用列表中的內容和(2)可以作爲參數發送到通用列表參數的方法。

  1. 可以插入的Apple亞型到​​因爲綁定類型參數是一個基類,其具有引用其所有亞型的能力。

  2. 如果Jonathan是不是超級型Apple,那麼它一般不正確的嘗試和發送的Jonathan列表,以這種方法,因爲我會允許插入Apple s轉換的Jonathan的List。然後,您將有類型Jonathan的引用訪問它不知道的對象的屬性和方法,這不是類型安全的。