我已阅读有关 generics get and put rule 的内容这应该会阻止您添加 Banana
到 List<? extends Fruit>
:
public abstract class Fruit { }
public class Banana extends Fruit { }
public class Apple extends Fruit { }
List<? extends Fruit> lst = new ArrayList<>();
lst.add(new Banana()); // Compile error "The method add(capture#6-of ? extends Fruit) in the type List<capture#6-of ? extends Fruit> is not applicable for the arguments (Banana)"
据我所知,如果您没有编译错误,您将能够执行以下操作:
List<? extends Fruit> lst = new ArrayList<>();
lst.add(new Banana());
lst.add(new Apple());
这听起来是错误的,因为你在同一个列表中得到了不同的对象类型(我看到@Tom Hawtins的回答解释了原因,我相信他:)(但我找不到它的链接))。
但是,如果您实现以下操作:
public class ListFruit implements List<Fruit> {
List<Fruit> list;
public ListFruit() {
list = new ArrayList<>();
}
@Override public int size() { return list.size(); }
// All delegates of "list"
@Override public List<Fruit> subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); }
}
然后执行:
ListFruit lst = new ListFruit();
lst.add(new Banana());
lst.add(new Apple());
for (Fruit fruit : lst)
System.out.println(fruit.getClass().getName());
没有编译错误,并且有以下(预期)输出:
Banana
Apple
我这样做是否违反了任何契约(Contract)?或者我是否规避了保护并且不应该这样做?
最佳答案
不,有两种不同的 Fruit
绝对没问题。在 List<Fruit>
.
当您实际创建了 List<Banana>
时,问题就出现了。 。例如:
List<Banana> bananas = new ArrayList<>();
bananas.add(new Banana());
// This is fine!
List<? extends Fruit> fruits = bananas;
// Calling fruits.get(0) is fine, as it will return a Banana reference, which
// is compatible with a Fruit reference...
// This would *not* be fine
List<Fruit> badFruits = bananas;
badFruits.add(new Apple());
Banana banana = bananas.get(0); // Eek! It's an apple!
关于java - 克服泛型投入-获取规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22786950/