2012-09-06 35 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的引用访问它不知道的对象的属性和方法,这不是类型安全的。

相关问题