为什么它会在第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 {
}
答案 0 :(得分:5)
Collection<? extends Fruit> col
表示col
是Collection
的{{1}}或某个Fruit
子类的Collection
,例如{ {1}}或Fruit
。
您无法将Collection<Apple>
添加到可能是Collection<Banana>
的{{1}}。
如果您希望能够添加任何Apple
,请将签名更改为:
Collection
答案 1 :(得分:0)
集合只能包含某种类型的条目及其子类型。例如,如果您有Collection<Banana>
,它只能包含香蕉。
尽管Banana
是Fruit
的子类,但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>
,但您只能使用没有通用输入参数的方法。
例如,您可以使用retainAll
,remove
和其他一些内容来改变集合,您可以使用所有只读操作,但不能add
新苹果到你的香蕉系列。