2014-09-23 28 views
0

我知道有很多關於類似問題的問題,但我還沒有找到一個直接解決這個問題。獲得類<Foo<T>>在運行時給定泛型類型輸入

這裏是代碼的骨架,我想實現:

class MyObj<T> { 
    // Internals are unimportant ... 
} 

private <T> void foo(T arg) { 
    Class<MyObj<T>> clazz = // What do I write here? 

    // Here is one thing that works, but is quite ugly: 
    @SuppressWarnings("unchecked") 
    clazz = (Class<MyObj<T>>)(new MyObj<T>().getClass()) 

    // ... 

    // Later, clazz is passed to a constructor of some other class 
    OtherClass<MyObj<T>> foo = new OtherClass<>(clazz); 
} 

問題1:沒有人有如何填充clazz更好的建議?理想情況下,它會避免撥打new

問題2:鑑於上面的醜陋(但工作)的代碼,有沒有可能會破壞的任何情況?我不喜歡@SuppressWarnings,並擔心我可能隱藏的問題。

+0

相關:[如何從具有泛型的類訪問.class(http://stackoverflow.com/questions/17634631/how-to-access-the-class-from-a-class-with -a-generic) – rgettman 2014-09-23 17:23:10

+0

由於擦除,'類>'將被綁定到任何「對象」。取而代之的是使用'類'可能會更好。這樣,你也可以通過'arg.getClass()'從'arg'中提取類信息。 – Makoto 2014-09-23 17:23:18

+1

你想用'clazz'做什麼? – 2014-09-23 17:23:21

回答

3

爲了避免實例化,你可以寫:

Class<MyObj<T>> clazz = (Class) MyObj.class; 

由於擦除,存在對MyObjClass情況下,無論任何類型參數的可能也有,所以雖然這是醜陋的,它是安全的。

+0

謝謝,這個作品!我還在另一個問題中看到了以下變體:'clazz =(Class >)(Class )MyObj.class'。有趣的是,在這種情況下如何進行雙重演出...... – jwd 2014-09-23 17:54:29

+0

@jwd:想象一下,您希望從「Integer」轉換爲「String」。它們是不兼容的類型,所以你不能寫'String s =(String)i':編譯器可以知道這不是O.K.你必須上傳到'Object'和*然後* downcast到'String':'String s =(String)(Object)i'。 (當然,你會得到一個'ClassCastException'。)就類型系統而言,這是一回事;您需要將您的'類'上傳到'Class'或'Class ',以便誘使編譯器讓您下調到'Class >'。 * [續] * – ruakh 2014-09-23 18:13:50

+0

* [續] *原因是我的版本只需要一個明確的演員陣容 - 向'Class'上傳,沒有向下降級到'Class >' - 原始類型需要特殊處理Java,並允許您隱式(和不安全地)轉換爲任何相應的參數化類型。 – ruakh 2014-09-23 18:15:15