2013-02-04 47 views
3

我有一個類似於遞歸的泛型方法,但爲每個調用調用方法的不同實例。是什麼導致與Java泛型和反射這個編譯錯誤?

public <M extends A> void doSomething(Class<M> mClass, M mObject) 
{ 
    // ... Do something with mObject. 

    A object = getObject(); 
    Class<? extends A> objectClass = object.getClass(); 

    doSomething(objectClass, objectClass.cast(object)); // Does not compile. 
} 

private A getObject() {...} 

的問題是有註釋的行不能編譯,給了以下錯誤:

The method doSomething(Class, M) in the type MainTest is not applicable for the arguments (Class, capture#3-of ? extends A)

我不太明白爲什麼編譯器不能編譯,如果它可以調用doSomething的M =「?擴展A」。

爲什麼不編譯?

+1

泛型請。 Java中沒有模板。 – EJP

回答

2

該語言不跟蹤這樣的通配符(看起來)。你需要做的是捕獲通配符,這可以通過類型推斷的方法調用完成。

public <M extends A> void doSomething(Class<M> mClass, M mObject) { 
    // ... Do something with mObject. 

    A object = getObject(); 
    Class<? extends A> objectClass = object.getClass(); 
    privateSomething(objectClass, object); 
} 
private <T extends A> void privateSomething(Class<T> objectClass, A object) { 
    doSomething(objectClass, objectClass.cast(object)); // Should compile. 
} 

一如往常,而反射具有一定的用途,它通常是混亂的跡象。

+0

完全同意你的最終評論。 – EJP

4

確定這裏是一個原始的解釋

你輸入你的方法,這樣它會接受中號是的

亞型現在您呼叫使用「對象類」,這是一個亞型的方法的但不一定M.的亞型

因此,編譯器抱怨......

如果你能解釋一下你正在嘗試做的多一點,我可以用這樣有利於lution。

+0

感謝您的回答。但爲什麼編譯器沒有實例化另一個'doSomething'方法呢?這是一種通用的方法。 –

+0

它會在Java 1.5之前工作,但在Java 1.5之後,編譯器無法找到匹配的調用方法簽名... –

+1

@LeonardoRaele您在製作標題時犯的錯誤相同。這是泛型,而不是模板。編譯器不會在泛型中「實例化」任何東西。你仍然在考慮模板。模板是生成新類型的一種方式:泛型是限制現有類型的一種方式。 – EJP

1

當您要求編譯器執行轉換時,必須知道執行轉換的確切類型。僅僅告訴編譯器你並不知道它是A的子類的確切類型摘要。

類告訴編譯器該對象的類型是A的子類,但它不告訴編譯器用於鑄造的確切類型。

你的問題是你試圖用泛型替換多態性。正如你正在努力學習,Generic並不是做現代多元化的新現代方式。