41

我有一个关于泛型的 Java 问题。我宣布了一个通用列表:

List<? extends MyType> listOfMyType;

然后在某种方法中,我尝试实例化并将项目添加到该列表中:

listOfMyType = new ArrayList<MyType>();
listOfMyType.add(myTypeInstance); 

WheremyTypeInstance只是一个类型的对象MyType;它不会编译。它说:

List<capture#3-of ? 类型中的方法 add(capture#3-of ? extends MyType) extends MyType> 不适用于参数 (MyType)

任何的想法?

4

5 回答 5

34

您不能对 extends 进行“放置”。查看泛型 - 获取和放置规则

于 2009-05-27T21:16:30.740 回答
28

考虑:

class MySubType extends MyType {
}

List<MySubType> subtypeList = new ArrayList<MySubType>();
List<? extends MyType> list = subtypeList;
list.add(new MyType());
MySubType sub = subtypeList.get(0);

sub现在包含一个MyType非常错误的。

于 2009-05-27T21:29:49.077 回答
6

您不需要在您的情况下使用通配符捕获语法,只需声明

List<MyType> listOfMytype;

应该足够了。如果你想确切地知道为什么,Java 泛型教程比你想知道的更多关于 Java 泛型的深奥疯狂。第 20 页针对您的具体情况。

至于为什么使用通配符捕获添加不起作用,这是因为编译器无法准确确定列表在每种情况下都是 MyType 的哪个子类,因此编译器会发出错误。

于 2009-05-27T21:29:47.233 回答
3

这里有一个类似的线程: 如何将元素添加到通配符通用集合中?

要了解泛型的工作原理,请查看以下示例:

    List<SubFoo> sfoo = new ArrayList<SubFoo>();
    List<Foo> foo;
    List<? extends Foo> tmp;

    tmp = sfoo;
    foo = (List<Foo>) tmp;

问题是,这不是为局部/成员变量设计的,而是为函数签名设计的,这就是它如此落后的原因。

于 2011-03-23T13:16:05.267 回答
3

我不知道这是否真的对你有帮助,但这是我在调用 Spring Framework 的泛型方法并希望返回泛型列表时必须使用的东西:

public <T> List<T> findAll(String tableName,Class<?> table) {
    String sql = "SELECT * FROM "+ tableName ;
    List<?> entities = getSimpleJdbcTemplate().query(sql,
            ParameterizedBeanPropertyRowMapper.newInstance(table));
            return (List<T>) entities;
}

似乎参数化需要您使用 ? 登录列表以接收结果,然后将列表转换为预期的返回类型。

我仍然对仿制药感到眼花缭乱......

于 2012-03-16T01:19:58.067 回答