【发布时间】:2016-02-22 22:38:59
【问题描述】:
在处理 Java 8 流时,我遇到了一个错误,编译器似乎“忘记”了我的泛型参数的类型。
下面的 sn-p 创建一个类名流并尝试将该流映射到Class<? extends CharSequence> 的流。
public static Stream<Class<? extends CharSequence>> getClasses() {
return Arrays.asList("java.lang.String", "java.lang.StringBuilder", "Kaboom!")
.stream()
.map(x -> {
try {
Class<?> result = Class.forName(x);
return result == null ? null : result.asSubclass(CharSequence.class);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
})
//.filter(x -> x != null)
;
}
当我取消注释过滤器以从流中删除空条目时,我得到一个编译错误
类型不匹配:无法从 Class
扩展为 Class
谁能解释一下为什么添加过滤器会导致这个错误?
PS:这里的代码有些随意,很容易消除错误:在应用过滤器之前将映射流分配给一个临时变量。我感兴趣的是为什么上面的代码sn-p会产生编译时错误。
编辑:正如@Holger 指出的,这个问题不是Java 8 Streams: why does Collectors.toMap behave differently for generics with wildcards? 的完全重复,因为有问题的sn-p 目前编译没有问题,而这里的sn-p 没有。
【问题讨论】:
-
嗯。起初我以为这是由于method chaining,但实际上我不确定。
asSubclass确实返回了Class<? extends CharSequence>。它也不能与javac一起编译,至少 1.8.0_74。 -
我可以通过对
filter的调用以及对map的显式类型参数进行编译:.<Class<? extends CharSequence>>map(。或者我可以在catch块之后使用return CharSequence.class而不是return null编译它。这看起来像是类型推断的问题。 -
只是一些旁注:使用
Stream.of(…)而不是Arrays.asList(…).stream(),进一步Class.forName永远不会返回null,因此条件已过时。当filter仅处理map的错误条件(即null测试)时,您始终可以使用flatMap(…)合并.map(…).filter(…)。综上所述,您可以将您的任务解决为return Stream.of("java.lang.String", "java.lang.StringBuilder", "Kaboom!") .flatMap(x -> { try { return Stream.of(Class.forName(x).asSubclass(CharSequence.class)); } catch(Exception e) { e.printStackTrace(); return null; }}); -
@Tunaki:不幸的是,它不是重复的,因为链接问题的问题已得到修复,而所有版本都会出现此问题,包括最新版本。
-
@Tunaki:确实,我不知道我从哪里复制了你的名字。真正让我困惑的是,在被拒绝的
.filter(…)之后简单地附加.map(Function.identity())会使错误消失。链接另一个.filter(x->true)甚至是一个简单的.unordered()会使它重新出现,添加另一个map(x->x)或.flatMap(Stream::of)将再次修复它。你可以继续……唯一重要的是链的最后一个操作。
标签: java eclipse java-8 java-stream