Java <! - ? extends Collection - >

时间:2016-06-03 11:43:24

标签: java generics collections

我有以下Java代码:

List<? extends Collection<String>> attributes = new ArrayList<HashSet<String>>(nrAttributes);

...

attributes.replaceAll((in) -> {
        List<String> out = new ArrayList<>(); 
        out.addAll(in); 
        return out;
    });

但它给了我一个编译器异常(最后一个是红色)说:

类型不匹配:无法从List转换为捕获#2-of?扩展集合

4 个答案:

答案 0 :(得分:2)

命令行说:

J:\WS\Java test>javac Main.java -Xdiags:verbose
Main.java:11: error: method replaceAll in interface List<E> cannot be applied to given types;
        attributes.replaceAll((in) -> {
                             ^
  required: UnaryOperator<CAP#1>
  found: (in)->{ Li[...]ut; }
  reason: argument mismatch; bad return type in lambda expression
      List<String> cannot be converted to CAP#1
  where E is a type-variable:
    E extends Object declared in interface List
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Collection<String> from capture of ? extends Collection<String>
1 error

即。 ?捕获可能是List<String>的子类型或兄弟,因此向List<String>添加List<? extends Collection>是不安全的。 ...extends Collection在这里并不重要。

可能的解决方案:

List<? extends Collection<String>> attributes = new ArrayList<HashSet<String>>(nrAttributes);

...

List<List<String>> attribs2 = new ArrayList<>();

attributes.forEach((in) -> {
    List<String> out = new ArrayList<>();
    out.addAll(in);
    attribs2.add(out);
});

或者:

List<Collection<String>> attributes = new ArrayList<>(nrAttributes);        

...

attributes.replaceAll((in) -> {
    List<String> out = new ArrayList<>();
    out.addAll(in);
    return out;
});

答案 1 :(得分:2)

扩展只会确保您从列表中 读取 Collection<String>。但你不能写它。

有一个非常好的解释,请参阅此link,其中我从以下地址获取了以下内容:

  

您无法向List<? extends T>添加任何对象,因为您不能   保证它真正指向什么样的List,所以你不能   保证该列表中允许该对象。唯一的   “保证”是你只能从它读取,你会得到一个T或   T的子类。

答案 2 :(得分:1)

您将attributes变量定义为扩展字符串集合的列表。在编译时,编译器无法确定attributes实际上是List<TreeSet<String>List<LinkedList<String>还是List<Vector<String>的实例。因此,编译器不允许您修改属性集合,因为您可能会将ArrayList<String>添加到另一个字符串集合的集合中(比如TreeSet<String>

通常,如果您有List<? extends Something>,编译器将不允许您修改集合(添加/删除/清除/ ...)。 使用? extends T键入的任何列表都是只读的!

编译:

List<Collection<String>> attributes = new ArrayList<>(nrAttributes);

答案 3 :(得分:-1)

当你说List&gt;你说的是“一个特定的集合子类型列表” 所有这些? extends X在内部被命名为capture #n of?扩展X(第一次捕获#1 ......,第二次捕获#2 ......等等),但每次都被认为是特定类型。例如,以下代码也没有编译,具有相同的错误

为什么需要仿制药?以下示例可以包含Collection of String(compiles,btw)

的任何子类
    List<? extends Collection<String>> attributes = new ArrayList<HashSet<String>>(nrAttributes);

    attributes.replaceAll((in) -> {
        List<String> out = new ArrayList<>();
        out.addAll(in);
        return out;
    });