简体   繁体   English

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

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

Here is the test: 这是测试:

@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);
}

And here is the error: 这是错误:

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>

Of course, it can be fixed using the raw type trick. 当然,它可以使用原始类型技巧来修复。

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

But I'd like to understand the cause of this error. 但我想了解这个错误的原因。

Update : 更新

It's not a duplicate of Lists with wildcards cause Generic voodoo error which is about adding into an upper-bounded wildcard list; 它不是带有通配符列表的重复导致Generic voodoo错误 ,这是关于添加到上限通配符列表; this topic is also well described in Wildcard Guidelines . 通配符指南中也很好地描述了这个主题。

In my case I'm not trying to add something into the list as you can see above. 在我的情况下,我不会尝试在列表中添加内容,如上所示。

Also, the error messages are different. 此外,错误消息也不同。

There appears to be something wrong with the multiple levels of type inference here. 这里的多级类型推断似乎有问题。 With this line: 有了这条线:

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

With the call to map , you're attempting to convert the original Optional<Function<String, List<? extends String>>> 通过调用map ,您正在尝试转换原始的Optional<Function<String, List<? extends String>>> Optional<Function<String, List<? extends String>>> to a Optional<List<? extends String>> Optional<Function<String, List<? extends String>>>Optional<List<? extends String>> Optional<List<? extends String>> . Optional<List<? extends String>> Then, with orElse , you're attempting to convert that to a List<? extends String> 然后,使用orElse ,您尝试将其转换为List<? extends String> List<? extends String> . List<? extends String> It seems reasonable. 这看似合理。

I can get it to compile without resorting to casting to raw types, by giving the intermediate step an explicit type. 通过给中间步骤一个显式类型,我可以让它编译而不需要转换为原始类型。

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

This shows that if the compiler can infer the result of the call to map to be a Optional<List<? extends String>> 这表明如果编译器可以推断出map的调用结果是一个Optional<List<? extends String>> Optional<List<? extends String>> , then the call to orElse will compile. Optional<List<? extends String>> ,然后调用orElse将编译。

However, I can change the explicit type to something where the declaration of intermedSelector compiles, but the call to orElse does not compile. 但是,我可以将显式类型更改为intermedSelector的声明编译的内容,但是对orElse的调用不会编译。 I've changed the explicit type of interMedSelector from Optional<List<? extends String>> 我从Optional<List<? extends String>>更改了interMedSelector的显式类型Optional<List<? extends String>> Optional<List<? extends String>> to Optional<? extends List<? extends String>> Optional<List<? extends String>>Optional<? extends List<? extends String>> Optional<? extends List<? extends String>> Optional<? extends List<? extends String>> , with an added ? extends Optional<? extends List<? extends String>> ,添加? extends ? extends . ? extends

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

The error here is similar to the one you're getting: 这里的错误类似于你得到的错误:

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>

With your code, the compiler must be inferring something unexpected, yet related to, Optional<List<? extends String>> 使用您的代码,编译器必须推断出一些意外的,但与Optional<List<? extends String>> Optional<List<? extends String>> . Optional<List<? extends String>> I can't tell if the compiler's captured type is Optional<? extends List<? extends String>> 我不知道编译器的捕获类型是否是Optional<? extends List<? extends String>> Optional<? extends List<? extends String>> Optional<? extends List<? extends String>> or something else, but that appears to be why you're getting the error. Optional<? extends List<? extends String>>或其他东西,但这似乎是你得到错误的原因。

My solution 我的解决方案

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

can be expressed in one statement, if I supply the proper type parameter to the call to map , so the compiler doesn't infer something unexpected. 如果我为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