繁体   English   中英

泛型:上限有界通配符转换/投射错误

[英]Generics: Upper Bounded Wildcards conversion/casting error

这是测试:

@Test
public void genericsTest() {
    String s = "x";
    List<? extends String> strings = singletonList(s);
    Optional<Function<String, List<? extends String>>> optionalSelector = Optional.empty();
    optionalSelector.map(selector -> selector.apply(s)).orElse(strings);
}

这是错误:

java: incompatible types: java.util.List<capture#1 of ? extends java.lang.String> cannot be converted to java.util.List<capture#2 of ? extends java.lang.String>

当然,它可以使用原始类型技巧来修复。

    optionalSelector.map(selector -> selector.apply(s)).orElse((List)strings);

但我想了解这个错误的原因。

更新

它不是带有通配符列表的重复导致Generic voodoo错误 ,这是关于添加到上限通配符列表; 通配符指南中也很好地描述了这个主题。

在我的情况下,我不会尝试在列表中添加内容,如上所示。

此外,错误消息也不同。

这里的多级类型推断似乎有问题。 有了这条线:

optionalSelector.map(selector -> selector.apply(s)).orElse(strings);

通过调用map ,您正在尝试转换原始的Optional<Function<String, List<? extends String>>> Optional<Function<String, List<? extends String>>>Optional<List<? extends String>> Optional<List<? extends String>> 然后,使用orElse ,您尝试将其转换为List<? extends String> List<? extends String> 这看似合理。

通过给中间步骤一个显式类型,我可以让它编译而不需要转换为原始类型。

Optional<List<? extends String>> intermedSelector = optionalSelector.map(selector -> selector.apply(s));
intermedSelector.orElse(strings);

这表明如果编译器可以推断出map的调用结果是一个Optional<List<? extends String>> Optional<List<? extends String>> ,然后调用orElse将编译。

但是,我可以将显式类型更改为intermedSelector的声明编译的内容,但是对orElse的调用不会编译。 我从Optional<List<? extends String>>更改了interMedSelector的显式类型Optional<List<? extends String>> Optional<List<? extends String>>Optional<? extends List<? extends String>> Optional<? extends List<? extends String>> Optional<? extends List<? extends String>> ,添加? extends ? extends

Optional<? extends List<? extends String>> intermedSelector = optionalSelector.map(selector -> selector.apply(s));
intermedSelector.orElse(strings);

这里的错误类似于你得到的错误:

J.java:26: error: incompatible types: List<CAP#1> cannot be converted to CAP#2
    List<? extends String> result = intermedSelector.orElse(strings);
                                                            ^
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends String from capture of ? extends String
    CAP#2 extends List<? extends String> from capture of ? extends List<? extends String>

使用您的代码,编译器必须推断出一些意外的,但与Optional<List<? extends String>> Optional<List<? extends String>> 我不知道编译器的捕获类型是否是Optional<? extends List<? extends String>> Optional<? extends List<? extends String>> Optional<? extends List<? extends String>>或其他东西,但这似乎是你得到错误的原因。

我的解决方案

Optional<List<? extends String>> intermedSelector = optionalSelector.map(selector -> selector.apply(s));
intermedSelector.orElse(strings);

如果我为map的调用提供了正确的类型参数,则可以在一个语句中表示,因此编译器不会推断出一些意外的事情。

optionalSelector.<List<? extends String>>map(selector -> selector.apply(s)).orElse(strings);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM