我有以下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?扩展集合
答案 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;
});