泛型:尝试将参数化集合传递给List addAll方法

时间:2013-07-30 09:40:07

标签: java generics collections

我有代码(完整的源代码):

public class AutoConversionTest {

    @Test
    public void test_autoConversion() {
        Wrapper wrapper = new Wrapper();
        wrapper.setList(new ArrayList<Sub>());
        wrapper.addAll(new ArrayList<Sub>());
    }

    class Wrapper {
        List<? extends Super> list;

        public void setList(List<? extends Super> list) {
            this.list = list;
        }

        public void addAll(List<? extends Super> list) {
            this.list.addAll(list);  //TROUBLES!
        }
    }

    class Super {}

    class Sub extends Super {}
}

问题: Wy错误以及如何解决它?

已编辑:我的错误日志

java: no suitable method found for `addAll(java.util.List<? extends expectations.public_method.experiments.AutoConversionTest.Super>)`
 method `java.util.List.addAll(int,java.util.Collection<? extends expectations.public_method.experiments.AutoConversionTest.Super>)` is not applicable (actual and formal argument lists differ in length)
 method `java.util.List.addAll(java.util.Collection<? extends expectations.public_method.experiments.AutoConversionTest.Super>)` is not applicable (actual argument `java.util.List<? extends expectations.public_method.experiments.AutoConversionTest.Super>` cannot be converted to `java.util.Collection<? extends expectations.public_method.experiments.AutoConversionTest.Super>` by method invocation conversion)

3 个答案:

答案 0 :(得分:7)

List<? extends Super>表示:一些未知类型的列表,它扩展了Super。因此,您不能向此类列表添加任何内容(null除外),因为您不知道其元素的类型。如果编译器允许这样做,您可以将OtherSub的实例添加到List<Sub>,这会破坏列表的类型安全性。

Wrapper.list的类型更改为List<Super>

编辑:

修改后的代码:

class Wrapper {
    List<Super> list;

    public void setList(List<? extends Super> list) {
        this.list.clear();
        this.list.addAll(list);
    }

    public void addAll(List<? extends Super> list) {
        this.list.addAll(list);
    }
}

答案 1 :(得分:2)

List<? extends Super>表示该列表可以使用任何未知数,只要它是Super的子Super类。

不幸的是,你不能添加一个未知的(因为编译器不会通过某些“捕获”规则将元素的类型与列表匹配),除了null。

最好的原则是使用 PECS 原则( P roducer E xtends, C onsumer S uper)。看到您的list是消费者,您应该有List<? super Super>消费者未知数。

答案 2 :(得分:2)

我推断你希望类Sub将类Super扩展为:

class Super {}
class Sub extends Super {}

即使您按上述方式编写类,通配符也会阻止您向列表添加任何内容,因为它仅用于只读列表。您可以使用类Wrapper执行以下任务:

public class Wrapper<T extends Super> {

    private List<T> list = new ArrayList<T>();

    void doStuff(){
        List<Sub> al = new ArrayList<Sub>();
        for(Sub s : al)
            list.add((T) s);
    }

}