2010-10-01 102 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) {} 
} 
相关问题