【问题标题】:Insert a BaseClass instance into a List<? extends BaseClass> (Java)将 BaseClass 实例插入 List<?扩展 BaseClass> (Java)
【发布时间】:2014-10-10 16:11:39
【问题描述】:
我有一个List<? extends MyClass> list,我想将其类扩展为MyClass 的对象和作为MyClass 实例的对象添加到此列表中:
list.add(new ClassThatExtendsMyClass());
list.add(new MyClass());
但eclipse显示构建错误:
方法 add(capture#9-of ? extends MyClass) 在
类型列表不是
适用于参数(MyClass)
我该如何解决这个问题?
【问题讨论】:
标签:
java
list
generics
inheritance
【解决方案1】:
Java 关键字 extends 在泛型引用类型中用于限制实际泛型类型实现派生度不低于命名类型。特别是它可以是一个子类。如果 type 用于提取值并对其进行操作,则应使用它。然后,您使用与该类的实际类型(实现/实现)无关的基类接口。
当您有一个特定的类并且需要传递(放入)到集合或其他通用类对象时,指向该对象的引用应该具有 super 关键字,它将实际对象限制为派生的对象比命名的类型多。
下面的代码示例。假设我们有类Base和Derived,其中Derived extends Base,类Base有一个接口方法foo(),并且都有默认构造函数。
void service() {
List<Base> theList = new ArrayList<Base>();
produceObjects(theList);
consumeObjects(theList);
}
void produceObjects(List<? super Base> consumerList) {
consumerList.add(new Derived());
}
void consumeObjects(List<? extends Base> producerList) {
for (Base base : producerList) {
base.foo();
}
}
【解决方案2】:
您可以将您的参考声明为List<MyClass>。
您将能够添加任何扩展 MyClass 的内容,包括 MyClass 的实例。
【解决方案3】:
这是不可能的。 List<? extends MyClass> list 实际上可以指向 ArrayList<ClassThatExtendsMyClass>。不能包含 MyClass 的其他子类的实例。
List<? extends Number> numbers = new ArrayList<Integer>();
numbers.add(Long.valueOf(2)); // not possible since 'Integer' array can't hold Longs
如果你想添加一些东西,你应该将你的变量'list'声明为List<? super MyClass>。这将使您能够将“MyClass”的任何子类添加到列表中。
List<? super Number> numbers = new ArrayList<Number>();
numbers.add(Long.valueOf(2));
这被称为“获取”和“放置”原则。如果你想“获取”东西,你需要使用List<? extends MyClass> 语法,而如果你想“放置”东西,你需要使用List<? super MyClass> 语法。当然如果你需要两者都做,那么你需要使用List<MyClass> 语法。
【解决方案4】:
试试这个:
List<MyClass>
它应该可以工作