我有以下测试代码:
public interface Container<I> {
public void addClass(Class<?> clazz);
}
public class MyContainer implements Container {
public void addClass(Class<?> clazz) {}
}
我在尝试编译这两个类时遇到以下错误:
MyContainer.java:1:MyContainer不是抽象的,不会覆盖Container中的抽象方法addClass(java.lang.Class)
如果我在MyContainer中向Container界面添加一个类型(例如<Object>
),我就不会收到错误。
问题是我将类型参数引入到Container,它是公共API的一部分,因此为了兼容性,我不能让所有实现类都无法编译。
有人有什么想法吗?这是类型擦除问题吗?有解决方法吗?
答案 0 :(得分:7)
我认为问题在于,如果你在类声明中的任何地方使用原始类型,那么你就会选择退出泛型。所以这将有效 - 请注意参数更改。
public class MyContainer implements Container {
public void addClass(Class clazz) {}
}
超类(分别为 原始类型的超级接口) 超类的擦除 (超级接口)的任何一个 参数化调用。
我相信这是相关位...... Container<T>.addClass(Class<?> clazz)
的删除是addClass(Class clazz)
。
但是,基本上除非这是真正的遗留代码,否则你应该考虑将一个类型参数作为一个重大变化引入接口。
答案 1 :(得分:3)
如果<?>
修复了它,那就摆脱它:
public void addClass(Class clazz) {}
错误消息不是很具描述性:
名称冲突:MyContainer类型的方法addClass(Class)与Container类型的addClass(Class)具有相同的擦除,但不会覆盖它
这意味着当它们的类型被擦除时,两个方法都是相同的,但是子类方法实际上并没有实现/覆盖超类/接口中的方法。这没有多大意义,我认为这是因为你选择不在你的子类中使用泛型,你必须坚持(而不是perameterize Class
)
答案 2 :(得分:3)
如果你的班级使用泛型,那么一个简单的解决方案就是:
interface Container<I> {
public void addClass(Class<?> clazz);
}
class MyContainer<I> implements Container<I> {
public void addClass(Class<?> clazz) {}
}
或者,如果您已经知道您拥有的Container类型,
class MyContainer implements Container<ContainerType> {
public void addClass(Class<?> clazz) {}
}
如果您的班级不使用Generics(1.5之前版本),则您不能拥有<?>
部分。所以这里不会有任何实际问题。
class MyContainer implements Container {
public void addClass(Class clazz) {}
}
答案 3 :(得分:0)
按如下方式实现您的界面应该有效(根据类型擦除):
public class MyContainer implements Container {
public void addClass(Class clazz) {}
}