![](/img/trans.png)
[英]Java Generics compile error in line class HanoiStack<T extends Comparable<T>> extends Stack<T>
[英]Java generics compile error involving Class<? extends T>
這個程序不編譯:
public class xx {
static class Class1<C> {
void method1(C p) {
}
}
static class Class2<T> extends Class1<Class<? extends T>> {
T object;
void method2() {
this.method1(this.object.getClass());
}
}
}
錯誤是:
xx.java:10: method1(java.lang.Class<? extends T>) in xx.Class1<java.lang.Class<? extends T>>
cannot be applied to (java.lang.Class<capture#215 of ? extends java.lang.Object>)
this.method1(this.object.getClass());
為什么會這樣? 為什么編譯器似乎相信object.getClass()
返回Class<? extends Object>
Class<? extends Object>
而不是Class<? extends T>
Class<? extends T>
?
您的代碼中的T
上沒有上限設置,所以? extends T
? extends T
真的無異於? extends Object
? extends Object
。 就在昨天,我玩了一個類似的例子,並打了這個障礙。 我有
static <T> T newInstance(T o) throws Exception {
final Class<? extends T> c = o.getClass();
return c.newInstance();
}
它抱怨同樣的錯誤。 考慮一下: Object.getClass()
的返回類型是Class<?>
,編譯器想要捕獲?
成為具體類型。 但相反,我們不想捕獲?
,但要“捕獲上限” T
- 並且在Java的泛型中沒有這樣的東西。
Object.getClass()
被定義為返回一個Class<? extends |T|>
Class<? extends |T|>
,其中T
是靜態已知類型的接收器(調用對象getClass()
)。 特別注意垂直條, 擦除操作符 。 類型變量的擦除是其最左邊界的擦除。 在你的情況下,這是隱式綁定Object
。 所以你得到一個Class<? extends Object>
Class<? extends Object>
,而不是Class<? extends T>
Class<? extends T>
。
這是為什么?
想象一下T = List<Integer>
,如果沒有未經檢查的警告 ,您可以突然執行以下操作:
List<String> myStrings = new ArrayList<>();
List<Integer> myInts = new ArrayList<>();
List<Integer> myIntyStrings = myInts.getClass().cast(myStrings);
myIntyStrings.add(-1);
String myString = myStrings.get(0); // BANG!
但幸運的是,我們確實收到警告..;)
根據getClass()的文檔,返回的對象的類型為Class< ? extends |X| >
Class< ? extends |X| >
Class< ? extends |X| >
,其中|X|
是調用該方法的實例類型的擦除。
因此,在類型為T
的對象上調用getClass()會返回Class< ? extends Object >
Class< ? extends Object >
。 我們在此API中沒有關於T
綁定信息。
通常,在泛型類上使用反射的API要求客戶端將類型為Class< T >
的附加參數傳遞給相關的構造函數或泛型方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.