2012-08-28 51 views
2

考慮以下功能:僞重載在Java中

public static <T> T doSomething(Document doc, String xpath, Class<T> returnType); 

的想法是處理XML文檔,檢索在指定的XPath的對象,並返回指定類型的東西,很簡單。現在,我們假設我們要這樣做,以便如果returnType.isEnum(),我們想把它看作是我們想要檢索String而不是枚舉類型,然後最終使用Enum.valueOf()

不幸的是,它會出現

String returnedObj = String.class.cast(...); // Returned value from the actual XPath.evaluate() call 
return Enum.valueOf(returnType, returnedObject); 

不起作用,因爲returnType不是Class<T extends Enum<T>>。但是,您無法通過Class.asSubclass()(至少沒有不安全的投射,我們試圖避免)塑造returnType

它似乎也不能超載doSomething()爲了做一些枚舉特定的 - 即。

public static <T extends Enum<T>> T doSomething(Document doc, String xpath, Class<T> returnType); 

因爲這實際上是「相同的簽名」運行時明智的。

因此,問題是,是否有辦法在一種方法中安全地完成所有這些操作,還是需要一種單獨的方法來專門處理枚舉或求助於不安全的投射?

+4

度過一個不安全的表演。 Java不能證明它是安全的,但你可以。 –

+3

@KelvinChung不要使用'String.class.cast'這是很難閱讀和完全不必要的。只需使用普通的演員表 – Jeffrey

回答

1

我對這個問題很感興趣,試試看。我沒有成功,但我認爲這是值得在這裏分享的嘗試,爲進一步討論的利益。

interface Evaluator { 
    <T> T evaluate(String path, Class<? extends T> type); 
} 


final class Attempt implements Evaluator { 
    @Override 
    public <T> T evaluate(String path, Class<? extends T> type) { 
    final Object result = evaluatePath(path, type); 
    return type.cast(type.isEnum() ? 
        valueOf(type.asSubclass(Enum.class), (String)result) : 
        result); 
    } 


    private static Object evaluatePath(String path, Class<?> type) { 
    /* This doesn't actually do anything meaningful, but that doesn't matter for now. 
     Presumably it would make a call to something like XPath#evaluate(). 
    */ 
    return path; 
    } 


    private static <T extends Enum<T>> T valueOf(Class<T> type, String name) { 
    return Enum.valueOf(type, name); 
    } 
} 

此代碼傳遞的IntelliJ IDEA的爲你型編譯器,但交房時實際的javac失敗:

[unchecked] unchecked method invocation: 
    <T>valueOf(java.lang.Class<T>,java.lang.String) in Attempt is applied to 
    (java.lang.Class<capture#474 of ? extends java.lang.Enum>,java.lang.String) 

我發現該錯誤消息百思不得其解,我認爲這是一個不好表達了通過原始類型Enum(如在Class<Enum>中)尋找參數化類型的方法的後果。

爲了確認在這裏需要可惡的鑄造,我鼓勵其他人編輯(或複製和擴充)上面的代碼以說明所需的更改。

+0

試試=> @SuppressWarnings(「unchecked」)。你的方法工作正常。 –

+0

是的,我預計它會毫無困難地運行,但最初的問題是尋找某種方式來寫這個,而不採用任何警告抑制。那麼再讀一遍,它會提到「不安全的鑄造」。在這種情況下,我們面臨着一個可遏制的警告,但我們有信心可以忽略。 – seh