簡體   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