2012-05-17 40 views
45

我有以下類和接口:方法參數延伸類實現接口

public class BasicObject{...} 
public interface CodeObject{...} 

我想創建一個方法,其中,參數需要是類型BasicObject的並實現CodeObject。我試過這段代碼,但它並不保證clazz是一個實現CodeObject的類。

myMethod(Class<? extends BasicObject> clazz){...} 

我想要做somethign這樣但是這個代碼不編譯:

myMethod(Class<? extends BasicObject implements CodeObject> clazz){...} 
+0

這似乎是回答相同的問題:http://stackoverflow.com/questions/745756/java-generics-wildcarding-with-multiple-classes – yiannis

回答

61

你的模式類必須擴展BasicObject和擴展/實現CodeObject(這實際上是一個跨面對)。您可以在方法簽名的通配符定義中聲明多個類,這樣做:

public <T extends BasicObject & CodeObject> void myMethod(Class<T> clazz) 

請注意,如果你做任何的這些方式,它不會工作:

  • public <T extends BasicObject, CodeObject> void myMethod(Class<T> clazz)

    這是技術上有效的語法,但CodeObject未使用;該方法將接受任何擴展了BasicObject的類,而不管它們是否擴展/實現了CodeObject

  • public void myMethod(Class<? extends BasicObject & CodeObject> clazz)
    public void myMethod(Class<? extends BasicObject, CodeObject> clazz)

    這些都是根據Java的只是錯誤的語法。

+3

關於帶「,」 ,「CodeObject」的目的是什麼?該類從「BasicObject」擴展,但「CodeObject」又如何? –

+3

對我來說,它只適用於僅使用T作爲參數類型(無Class)的情況。整行: 'public void myMethod(T clazz)' –

+0

然後在該方法中,如何在clazz對象上調用屬於'BasicObject'的getter? – OrangePot

0

如果不是所有BasicObjects實施CodeObject,那麼你可以使用一個instanceof/Class.isInstance()檢查你的方法(見http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html):

myMethod(Class<? extends BasicObject> clazz) 
{ 
    if (!clazz.isInstance(CodeObject)) 
    { 
     (indicate that the call was incorrect) 
    } 
    ... 
} 
+4

是的,但我不想這樣做。當然,任何方法都可以使用myMethod(Object obj),然後使用'obj.isInstance(...)',但這就是我試圖避免的。我真的希望我的方法的用戶被迫傳遞一個好的參數。 – Gab

+0

那麼,如果你想-force-它可以讓你的程序在每次他們這樣做時崩潰(或者只是拋出一個IllegalArgumentException,我相信他們會以這種方式更快地找出它) – Riking

7

這是一個有點詳細的方法,但避免了泛型的麻煩。創造出不伸出/實施另一個類:

public abstract class BasicCodeObject 
    extends BasicObject 
    implements CodeObject {...} 

然後你的方法可以是:

public <T extends BasicCodeObject> void myMethod(Class<T> clazz) {...} 
4

有兩種方法,這取決於您是否希望您的問題通過一項類類型在你的方法參數可以擴展BasicObject並實現CodeObject類對象這樣做。兩者都有解決方案。

解決方案1:

如果你想通過Class本身,你可以做到這一點,正如@bontade解釋,

public <R extends BasicObject & CodeObject> void myMethod(Class<R> clazz) 

,如果你想通過class對象,可以寫

public <R extends BasicObject & CodeObject> void myMethod(R clazz) 

以上是處理泛型的更復雜的方法。

解決方案2:

以下是簡單的一個。您可以定義延伸要擴展和實現它的類抽象類:如果你想通過類本身現在

public abstract class TargetClassType extends BasicObject implements CodeObject { 

} 

,做

public void myMethod(Class<TargetClassType> clazz) 

,或者如果你想通過寫對象

public void myMethod(TargetClassType clazz) 

以上兩種解決方案都適合您的問題,但第二種解決方案更簡單。