簡體   English   中英

返回類型的推斷通配符泛型

[英]Inferred wildcard generics in return type

Java通常可以根據參數推斷泛型(甚至在返回類型上,與例如C#相反)。

例證:我有一個泛型類Pair<T1, T2> ,它只存儲一對值,可以按以下方式使用:

Pair<String, String> pair = Pair.of("Hello", "World");

該方法of看起來就像這樣:

public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
    return new Pair<T1, T2>(first, second);
}

非常好。 但是,這不再適用於以下需要使用通配符的用例:

Pair<Class<?>, String> pair = Pair.of((Class<?>) List.class, "hello");

(注意顯式List.class以使List.class成為正確的類型。)

代碼失敗,出現以下錯誤(由Eclipse提供):

類型不匹配:無法從TestClass.Pair<Class<capture#1-of ?>,String>TestClass.Pair<Class<?>,String>

但是,顯式調用構造函數仍然按預期工作:

Pair<Class<?>, String> pair =
    new Pair<Class<?>, String>((Class<?>) List.class, "hello");

有人可以解釋這種行為嗎? 它是按設計的嗎? 需要嗎? 我做錯了什么,或者我偶然發現編譯器中的設計/錯誤存在缺陷?

狂野猜測:“捕獲#1-of?”似乎暗示通配符由動態編譯器填充,使類型成為Class<List> ,從而使轉換失敗(來自Pair<Class<?>, String> Pair<Class<List>, String> )。 這是正確的嗎? 有辦法解決這個問題嗎?


為了完整起見,這里是Pair類的簡化版本:

public final class Pair<T1, T2> {
    public final T1 first;
    public final T2 second;

    public Pair(T1 first, T2 second) {
        this.first = first;
        this.second = second;
    }

    public static <T1, T2> Pair<T1, T2> of(T1 first, T2 second) {
        return new Pair<T1, T2>(first, second);
    }
}

構造函數的工作原因是您明確指定了類型參數。 如果你這樣做,靜態方法也會起作用:

Pair<Class<?>, String> pair = Pair.<Class<?>, String>of(List.class, "hello");

當然,首先你有一個靜態方法的原因可能只是獲得類型推斷(根本不適用於構造函數)。

這里的問題(如你所建議的)是編譯器正在執行捕獲轉換 我相信這是[JLS的§15.12.2.6]的結果

  • 所選方法的結果類型確定如下:
    • 如果使用返回類型void聲明被調用的方法,則結果為void。
    • 否則,如果該方法需要未經檢查的轉換,則結果類型是方法聲明的返回類型的擦除(第4.6節)。
    • 否則,如果被調用的方法是通用的,那么對於1in,讓Fi成為方法的形式類型參數,讓Ai成為方法調用推斷的實際類型參數,並且讓R成為方法的聲明返回類型調用。 通過將捕獲轉換(第5.1.10節)應用於R [F1:= A1,...,Fn:= An]來獲得結果類型。
    • 否則,通過將捕獲轉換(第5.1.10節)應用於方法聲明中給出的類型來獲取結果類型。

如果你真的想要推理,一種可能的解決方法是做這樣的事情:

Pair<? extends Class<?>, String> pair = Pair.of(List.class, "hello");

變量pair將具有更寬的類型,並且它確實意味着在變量的類型名稱中輸入更多,但至少您不再需要在方法調用中進行轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM