[英]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.