2013-04-12 12 views
2

我有一個看起來像這樣的方法:傳遞一個運行時解析參數,其中有多個綁定類型的方法,編譯錯誤

public static <T extends Enum<T> & Marshallable> String foo(Collection<T> collection, Class<? extends Marshallable>... marshallables); 

所以我期待被傳爲實現Marshallable接口枚舉集。 它工作正常,如果我在運行時具體的枚舉類型,但我寫了一個測試方法,從類對象動態地創建一個枚舉列表(實現Marshallable),我無法將此列表傳遞給上面的方法。

@Test 
public void fooTest() { 
... 
if (clazz.isEnum()) { // collection enum xml 
    List<? extends Enum<? extends Marshallable>> enumList = (List<? extends Enum<? extends Marshallable>>) Arrays.asList(clazz.getEnumConstants()); 
--> String enumListXml = foo(enumList, clazz); 
... 

標記行會給出編譯錯誤。我無法弄清楚如何在不更改方法簽名的情況下傳遞列表。

回答

5

你需要使用一個通用的helper方法有一個未經檢查的轉換:

private static <T extends Enum<T> & Marshallable> void fooHelper(Class<? extends Marshallable> type) { 
    if (type.isEnum()) { 

     //This is safe because of the isEnum check, and we don't return any 
     //type with T (important because the caller can specify what T is). 
     @SuppressWarnings("unchecked") 
     final Class<T> enumType = (Class<T>)type; 

     final List<T> enumConstants = Arrays.asList(enumType.getEnumConstants()); 
     foo(enumConstants); 
    } 
} 

的原因,你的版本不工作是因爲T extends Enum<T> & MarshallableT遞歸的約束 - 這隻能表示與類型參數。 ? extends Enum<? extends Marshallable>中的通配符類型參數不再指定該關係。

警告:它的當務之急是fooHelper不返回包含T一個類型,因爲這可能會導致堆污染。例如:

private static <T extends Enum<T> & Marshallable> List<T> unsafeFooHelper(Class<? extends Marshallable> type) { 
    if (type.isEnum()) { 

     //no longer safe! 
     @SuppressWarnings("unchecked") 
     final Class<T> enumType = (Class<T>)type; 

     return Arrays.asList(enumType.getEnumConstants()); 
    } 
    return Collections.emptyList(); 
} 

enum Enum1 implements Marshallable { ONE, TWO } 

enum Enum2 implements Marshallable { A, B } 

... 

//caller lies about what T is: 
List<Enum2> enumConstants = Main.<Enum2>unsafeFooHelper(Enum1.class); 

//sometime later... 
Enum2 enumConstant = enumConstants.get(0); //ClassCastException 
+0

從Eclipse運行時它工作正常,但現在我注意到它編譯錯誤,當我做maven構建。我調用helper的那一行給出錯誤:「類型參數爲 void無法確定;對於類型變量T,沒有唯一的最大實例存在上限可執行」 – acheron55

+0

@ acheron55它似乎可以在[這裏](http:// ideone。 com/H3YslT)(sun-jdk-1.7.0_10)。你在使用Java 6或更早的版本嗎? –

+0

是的,我正在使用Java 6.我認爲它是類似的問題在這裏:http://stackoverflow.com/questions/314572/bug-in-eclipse-compiler-or-in-javac作爲一個解決方法,我不得不說謊T,通過傳遞一個「硬編碼的」enum&marshallable類型給helper調用,我不太喜歡。 MarshallingTest fooHelper(clazz所)。 – acheron55

相關問題