7

根据我阅读的文献,我们有 juicy fruits 实现了以下接口:

public interface Juicy<T> {
    Juice<T> squeeze();
}

使用有界类型变量,以下方法将取出一堆水果并将它们全部挤压:

<T extends Juicy<T>> List<Juice<T>> squeeze(List<T> fruits);

现在我们也需要如下的低级兄弟姐妹来工作:

class Orange extends Fruit implements Juicy<Orange>;
class RedOrange extends Orange;

所以我希望该方法如下所示:

<T extends Juicy<T>> List<Juice<? super T>> squeeze(List<? extends T> fruits);

相反,我发现方法签名如下:

<**T extends Juicy<? super T>>** List<Juice<? super T>> squeezeSuperExtends(List<? extends T> fruits);

是什么解释了这种差异?

4

2 回答 2

3

内部是这样的,它是的子类可以在其范围内<? super T><T extends Juicy<? super T>>RedOrangeJuicy<Orange>

想象一下没有第<? super T>一个:

public <T extends Juicy<T>> List<Juice<T>> squeeze(List<T> fruits) {...

现在T必须是一个Juicy<T>. 类Orange是一个Juicy<T>,它是一个Juicy<Orange>。但类RedOrange不是Juicy<T>. 这不是Juicy<RedOrange>; 这是一个Juicy<Orange>。因此,当我们尝试调用时squeeze

List<RedOrange> redOranges = new ArrayList<RedOrange>();
List<Juice<RedOrange>> juices = squeeze(redOranges);

我们得到以下编译器错误:

Inferred type 'RedOrange' for type parameter 'T' is not within its bound; should implement 'Juicy<RedOrange>'.

如果我们放置<? super T>, 则允许类型参数 forJuicy成为 的超类T。这允许RedOrange使用,因为它是Juicy<Orange>, 并且OrangeRedOrange.

public <T extends Juicy<? super T>> List<Juice<T>> squeeze(List<T> fruits) {...

现在对squeeze上面的调用编译。

编辑

但是如果我们想从squeezea中List<Juice<Orange>>得到 aList<RedOrange>怎么办?它有点棘手,但我找到了解决方案:

我们需要Orangesqueeze方法中匹配第二个类型参数:

public <S extends Juicy<S>, T extends Juicy<S>> List<Juice<S>> squeeze(List<T> fruits)

在这里,S代表Orange,以便我们可以返回List<Juice<Orange>>。现在我们可以说

List<RedOrange> redOranges = new ArrayList<RedOrange>();
List<Juice<Orange>> juices = squeeze(redOranges);
于 2013-05-07T17:31:10.223 回答
3

在我看来,考虑这一点的最简单方法是简单地忽略水果类型与其产生的果汁类型之间的关系。该链接是在类声明中建立的;我们不需要它来挤一堆Juicys。

换句话说,只需参数化 s 将产生的Juice类型Juicy

<T> List<Juice<T>> squeeze(List<? extends Juicy<? extends T>> fruits);

在这里,我们根据生产的常见超级类型Juice(即 的参数Juicy)而不是水果的常见超级类型来生成果汁列表。

然后我们得到以下信息:

//works
List<Juice<Orange>> b = squeeze(Arrays.asList(new Orange(), new RedOrange()));

//fails as it should 
List<Juice<RedOrange>> d = squeeze(Arrays.asList(new RedOrange()));
于 2013-05-07T17:45:21.590 回答