2010-10-01 43 views
6

類我有以下的測試代碼:不能編譯它實現的接口中,無類型參數

public interface Container<I> { 
    public void addClass(Class<?> clazz); 
} 

public class MyContainer implements Container { 
    public void addClass(Class<?> clazz) {} 
} 

,並試圖編譯這兩個類時,我收到以下錯誤:

myContainer中。 java:1:MyContainer不是抽象的,並且不覆蓋容器中的抽象方法addClass(java.lang.Class)

如果我向Container接口添加一個類型e在MyContainer中(例如<Object>),我沒有收到錯誤。

問題是我向容器引入了類型參數,它是公共API的一部分,所以爲了兼容性,我不能讓所有實現類都無法編譯。

任何人有任何想法?這是一個類型擦除問題?有沒有解決方法?

回答

7

我認爲問題在於,如果您在類聲明中的任何位置使用原始類型,那麼您可能會選擇使用泛型。所以這將工作 - 注意參數的變化。

public class MyContainer implements Container { 
    public void addClass(Class clazz) {} 
} 

section 4.8 of the JLS

的超類原料的類型(分別是 超接口)是超類 (超接口)的 擦除的任何其 參數調用的。

相信這是相關位...的Container<T>.addClass(Class<?> clazz)擦除爲addClass(Class clazz)

但是,基本上,除非這是真正的遺留代碼,否則應該將引入類型參數作爲突破性更改引入接口。

+0

@ Skeet-闡述將helpful..TIA – hakish 2010-10-01 11:07:14

+0

我看看,謝謝喬恩。公認。 – 2010-10-01 12:19:05

3

擺脫如果<?>修復它:

public void addClass(Class clazz) {} 

該錯誤消息是不是很描述:

名稱衝突:該方法addClass(類)類型myContainer中的具有擦除作爲相同類型Container的addClass(Class)但不覆蓋它

這意味着您的兩個方法在第eir類型被擦除,但子類方法實際上並未實現/覆蓋超類/接口中的一個。這沒有多大意義,我假設這是因爲你選擇不使用泛型在你的子類中,你必須堅持(而不是參數化)

3

如果你的類使用泛型,那麼一個簡單的解決方案會做到這一點:

interface Container<I> { 
    public void addClass(Class<?> clazz); 
} 

class MyContainer<I> implements Container<I> { 
    public void addClass(Class<?> clazz) {} 
} 

或者,如果你已經知道你有容器的類型,

class MyContainer implements Container<ContainerType> { 
    public void addClass(Class<?> clazz) {} 
} 

如果你的類不使用泛型(預1.5),那麼你不能有<?>部分。所以這裏不存在任何實際問題。

class MyContainer implements Container { 
    public void addClass(Class clazz) {} 
} 
0

實現你的界面如下圖所示應該工作(按類型擦除):

public class MyContainer implements Container { 
    public void addClass(Class clazz) {} 
} 
相關問題