gpt4 book ai didi

Java Stream 泛型类型不匹配

转载 作者:搜寻专家 更新时间:2023-10-30 19:47:22 26 4
gpt4 key购买 nike

在处理 Java 8 流时,我遇到了一个错误,编译器似乎“忘记”了我的泛型参数的类型。

以下代码片段创建了一个类名流,并尝试将该流映射到一个流 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)
;

}

当我取消注释过滤器以从流中删除空条目时,出现编译错误

Type mismatch: cannot convert from Class<capture#15-of ? extends CharSequence> to Class<Object>

有人可以向我解释为什么添加过滤器会导致此错误吗?

PS:此处的代码有些随意,很容易使错误消失:在应用过滤器之前将映射流分配给一个临时变量。我感兴趣的是为什么上面的代码片段会产生编译时错误。

编辑:正如@Holger 所指出的,这个问题与Java 8 Streams: why does Collectors.toMap behave differently for generics with wildcards? 不完全相同。因为那里有问题的片段目前编译没有问题,而这里的片段没有。

最佳答案

这是因为类型推断:

类型是从它的目标“猜测”出来的:我们知道 map(anything) 必须返回一个 "Stream<Class<? extends CharSequence>>"因为它是函数的返回类型。如果您将返回链接到另一个操作,例如过滤器或映射,我们将失去这种类型推断(它不能“通过”链接)

类型推断有其局限性,您会发现的。

解决方法很简单:你说过吗,如果你使用一个变量,你可以指定目标然后帮助类型推断。

这次编译:

public static Stream<Class<? extends CharSequence>> getClasses() {
Stream<Class<? extends CharSequence>> map1 = 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;
});
return map1.filter(x -> x != null);

请注意,我修改了代码以始终返回 null,以表明推断类型并非来自 lambda 返回类型。

我们看到 map1 的类型是由变量声明推断出来的,它的目标。如果我们返回它,它是等价的,目标是返回类型,但是如果我们链接它:

这不编译:

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) {

e.printStackTrace ();
}

return null;
}).filter(x -> x != null);

第一个 map 声明没有目标,因此默认定义推断类型:Stream<Object>

编辑

使其工作的另一种方法是使类型推断与 Lambda 返回值(而不是目标)一起工作,例如,您需要使用 cast 指定返回类型。这将编译:

public static Stream<Class<? extends CharSequence>> getClasses2 () {

return Arrays.asList ("java.lang.String", "java.lang.StringBuilder", "Kaboom!").stream ().map (x -> {
try {
Class<?> result = Class.forName (x);
return (Class<? extends CharSequence>)( result == null ? null : result.asSubclass(CharSequence.class));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace ();
}

return (Class<? extends CharSequence>)null;
}).filter(x -> x != null);

请注意,这是因为操作链,您可以将 .filter(x -> x != null) 替换为 map(x->x),您会遇到同样的问题。

编辑:修改示例以完全匹配问题。

关于Java Stream 泛型类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35565357/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com