【问题标题】:List<? extends MyType>列表<?扩展我的类型>
【发布时间】:2009-05-27 21:10:08
【问题描述】:

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

List<? extends MyType> listOfMyType;

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

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

其中myTypeInstance 只是MyType 类型的对象;它不会编译。它说:

方法 add(capture#3-of ? extends MyType) 在类型 List 不适用 对于参数(MyType)

有什么想法吗?

【问题讨论】:

  • 如果类 Bar 扩展类 Foo 并且类 Baz 具有 generic 那么 Baz waldo = new Baz() 将不起作用,因为 Baz 不是 Baz 的子类, Bar 是 Foo 的子类。子类不适用于泛型。 ArrayList flob = new ArrayList() 将不起作用。简单地说,继承不适用于泛型。既然你做了 List extends MyType> 你可以有 List = new ArrayList。因为他们不一样。没有布埃诺。

标签: java list generics bounded-wildcard


【解决方案1】:

您不能对 extends 进行“放置”。看Generics - Get and Put rule

【讨论】:

  • 正如 Josh Bloch 所说:“记住 PECS:生产者扩展,消费者超级。”由于 listOfMyType 是一个消费者(您正在添加它),super 有效,extends 无效。
  • 学究点:你可以putnull"with extends"。您还可以捕获您之前“得到”的类型和“放置”引用。
【解决方案2】:

考虑:

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,这是非常错误的。

【讨论】:

    【解决方案3】:

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

    List<MyType> listOfMytype;
    

    应该够了。如果您想确切地知道原因,Java Generics Tutorial 比您想知道的有关 Java 泛型深奥的疯狂的要多得多。第 20 页针对您的具体情况。

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

    【讨论】:

      【解决方案4】:

      这里有一个类似的线程: How can elements be added to a wildcard generic collection?

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

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

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

      【讨论】:

        【解决方案5】:

        我不知道这是否真的对你有帮助,但这是我在调用 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;
        }
        

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

        我仍然对泛型感到眼花缭乱......

        【讨论】:

        • 不要通过字符串连接创建 SQL 查询 - 请参阅 SQL 注入
        猜你喜欢
        • 2021-12-17
        • 1970-01-01
        • 1970-01-01
        • 2017-08-15
        • 1970-01-01
        • 1970-01-01
        • 2017-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多