2013-11-04 52 views
3

我遇到了仿製藥的問題,並且我想要的是在嘗試反映某些通用信息時進行類型擦除。意外類型擦除

我正在使用基於http://www.artima.com/weblogs/viewpost.jsp?thread=208860的類來做反射,但這不是問題。

下面的代碼演示了這個問題:

private <U extends MyClass1> U doSomething(MyClass2<U> p) { 
    Class<U> classIWant = null; 
    for (Class<?> c : GenericTypeUtils.getTypeArguments(MyClass2.class, p.getClass()))  { 
     if (MyClass1.class.isAssignableFrom(c)) { 
      classIWant = c.asSubclass(MyClass1.class); 
      break; 
     } 
    } 
} 

不幸的是,線

classIWant = c.asSubclass(MyClass1.class); 

顯示以下錯誤

java: incompatible types 
    required: java.lang.Class<U> 
    found: java.lang.Class<capture#4 of ? extends MyClass1> 

,這就是真正的困惑我。 U擴展了MyClass1,因此U是MyClass1。

顯然有一些類型的擦除我不理解在這裏 - 請任何人都可以幫忙。順便說一句,這是Java的1.7.0_40

感謝

康拉德溫徹斯特

+0

你可以在這裏看一下 - http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens –

+1

這不會與類型擦除。擦除在編譯結束時發生,而您的錯誤在編譯期間發生。它會改爲不正確的使用泛型(我不太熟悉,對不起) –

回答

1

方法asSubclass()實現像這樣

public <U> Class<? extends U> asSubclass(Class<U> clazz) { 
    if (clazz.isAssignableFrom(this)) 
     return (Class<? extends U>) this; 
    else 
     throw new ClassCastException(this.toString()); 
} 

Class<? extends U>返回類型。請注意,您的UasSubclass方法中的U是完全無關的類型變量。

所以asSubclass()返回與在這種情況下的U,其中U一些未知亞型Class類型中聲明的值的方法是MyClass1

您正在試圖將此值分配給Class類型的一些亞型MyClass1的變量。編譯器不能保證它們匹配,因此不允許編譯。

如果您願意,您可以投射返回的值,但如果類型不匹配,最終可能會在運行時得到ClassCastException

+0

感謝您的非常明確的解釋 – Conrad

+0

@conrad歡迎您。 –

1

Java編譯器無法保證Class對象c與通用類型U匹配。由於類型擦除,編譯器要確保類型安全,並確保從c.asSubclass返回的Class匹配Class<U>,但它不能。

The asSubclass method返回Class<? extends U>。在Class類中,U表示傳入asSubclassClass的類型。當你打電話的時候,那是c。但是編譯器不能保證這種返回類型與你自己聲明的<U extends MyClass1>相符。它們可以是不同的MyClass1的子類。

如果您可以保證c.asSubclass將返回一個Class<U>,然後將它轉換爲Class<U>

classIWant = (Class<U>) c.asSubclass(MyClass1.class); 

您會收到一個「未投」的警告。這是因爲編譯器不能保證這真的是一個Class<U>,但你是這麼說的。請小心,因爲這可能會導致在其他地方難以跟蹤的ClassCastException,即使在您返回U之後。只有在您可以自己保證類型安全的情況下才能這樣做。

+0

謝謝 - 我試圖避免未經檢查的轉換異常,但看起來不可能。 – Conrad