收集<! - ?延伸T - >意味着什么?

时间:2017-11-09 11:36:55

标签: java

为什么它会在第23行抛出编译错误。'a'是Apple类的对象, col 是包含Apple对象的列表,但它仍然是抛出下面提到的编译错误:

类型Collection中的方法add(capture#1-of?extends Fruit)不适用于参数(Fruit)

public class Basket {
    List<Fruit> list;
    public Basket() {
        list = new ArrayList<>();
    }
    public Basket(List<Fruit> plist) {
        list = plist;
    }

   void addFruit(Collection<? extends Fruit> col) { // this does not work
// void addFruit(Collection<Fruit> col) { // this works
        Fruit a = new Apple();
        Apple a1 = new Apple();
        Fruit f1 = new Fruit();
        col.add(a);// line 23
    }

    int getSize() {
        return list.size();
    }

    public static void main(String[] args) {
        Fruit f1 = new Apple();
        Fruit f2 = new Apple();
        Fruit f3 = new Apple();
        List<Fruit> list = new ArrayList<>();
        list.add(f1);
        list.add(f2);
        list.add(f3);
        Basket b = new Basket(list);
        b.addFruit(list);
        System.out.println(b.getSize());
    }
}

class Fruit {
}

class Apple extends Fruit {
}

2 个答案:

答案 0 :(得分:5)

Collection<? extends Fruit> col表示colCollection的{​​{1}}或某个Fruit子类的Collection,例如{ {1}}或Fruit

您无法将Collection<Apple>添加到可能是Collection<Banana>的{​​{1}}。

如果您希望能够添加任何Apple,请将签名更改为:

Collection

答案 1 :(得分:0)

集合只能包含某种类型的条目及其子类型。例如,如果您有Collection<Banana>,它只能包含香蕉。

尽管BananaFruit的子类,但Collection<Banana>Collection<Fruit>不是类型兼容的。这可能看起来有点反直觉,但可以这样考虑:在Collection<Banana>中,您只期望Banana。你不期望Apple。但如果你有一个Collection<Fruit>,你就可以拥有各种各样的水果。你可以在这个系列中添加任何水果。

如果您将Collection<Banana>转换为Collection<Fruit>,则可以在其中添加苹果。然后你试着从你的Collection<Banana>中取出一根香蕉然后你会得到一个苹果。由于您无法将Apple强制转换为Banana,因此在运行时抛出ClassCastException并且您的代码失败。

因此,在您的情况下,您可能需要@Eran建议的Collection<Fruit>。但是,要详细回答您的问题:如果您有Collection<Banana>,则可以将该集合用作Collection<? extends Fruit>,但您只能使用没有通用输入参数的方法。

例如,您可以使用retainAllremove和其他一些内容来改变集合,您可以使用所有只读操作,但不能add新苹果到你的香蕉系列。