我有一個類,如下所示:如何在運行時將類<T>轉換爲類似<Class T extends Foo>的東西?
class FooClassAnalyser<T extends Foo> extends ClassAnalyser<T>
(其中ClassAnalyser
爲若干具體實施方式的一個抽象基類;和FooClassAnalyser
是的專業對於其中T
延伸Foo
的情況下的具體實現)。它有一個構造函數,看起來像這樣:
FooClassAnalyser(Class<T> classToAnalyse)
在另一類,我取決於classToAnalyse
的類型ClassAnalyser
個靜態工廠方法調用適當的構造函數:
static <U> ClassAnalyser<U> constructClassAnalyser(Class<U> classToAnalyse)
的功能我想要查看是否U instanceof Foo
,然後構造一個FooClassAnalyser
並返回它,如果是。
但是,我找不到一種方法來適應Java的類型系統。類型擦除意味着我們不能直接與U
做任何事情。然而,我們作爲一個參數能夠通過classToAnalyse
事實測試通過使用反射來看看U instanceof Foo
:
if (Foo.class.isAssignableFrom(classToAnalyse))
我的問題是,不像instanceof
,這種「通過反射的instanceof」不可見Java的類型系統。特別是,直接將classToAnalyse
作爲參數傳遞給FooClassAnalyser
的構造函數會因類型不匹配而失敗,因爲Java不知道classToAnalyse
實際上是Class<U extends Foo>
。
到目前爲止,我已經找到了最好的解決方案是使用未經檢查的鑄造,使classToAnalyse
一個Class<? extends Foo>
(這是實際上檢查,但Java的不知道它的選中)。至少可以將它作爲參數傳遞給new FooClassAnalyser
,並獲得返回的對象FooClassAnalyser<?>
。然而,問題在於,這不會轉換回ClassAnalyser<U>
,因爲Java不承認鑄造classToAnalyse
具有不同的泛型綁定,但不會改變對象仍然是相同對象的事實(因此仍然是Class<U>
);換句話說,所有Java可以看到的是它不認可的FooClassAnalyser<?>
也是FooClassAnalyser<U>
,因此轉換回來需要另一個未檢查的轉換。其結果是編譯和運行的代碼,但有許多關於類型安全性的警告。
我嘗試過的大多數其他事情都是語法錯誤(例如,類型Class<U extends Foo>
的變量不能直接聲明; Java不會正確解析)。應該指出,我實際上沒有任何一個類型爲U
的對象;我試圖分析課程本身,因此只有Class<U>
對象可以使用。
是否有可能以類型安全的方式編寫這樣的代碼?
對於它的價值,我認爲你可以做得比你現在做的更好(沒有經過檢查的劇組)。當你使用Java泛型稍微高級一些時,它總是會變得越來越糟糕。 – kaqqao
作爲一個方面說明,你不必使用未經檢查的強制轉換爲Class <?擴展Foo>'。你可以使用['clazz.asSubclass(Foo.class)'](http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#asSubclass-java.lang.Class- )。 – Radiodef
@Radiodef:是的,但'clazz.asSubclass(Foo.class)'返回一個'Class <?延伸Foo>',這已經失去了關於''的知識。你可以用它來構造一個'FooClassAnalyser <?在沒有警告的情況下安全地延伸Foo>',但沒有乾淨的方式將其作爲'ClassAnalyser '返回...... – Holger