无法编译实现没有类型参数的接口的类

发布于 2024-09-25 16:21:05 字数 577 浏览 5 评论 0原文

我有以下测试代码:

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 接口添加类型(例如 ),我没有收到错误消息。

问题是我向 Container 引入了类型参数,它是公共 API 的一部分,因此为了兼容性,我不能让所有实现类都无法编译。

有人有什么想法吗?这是类型擦除问题吗?有解决方法吗?

I have the following test code:

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

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

and I get the following error when trying to compile these two class:

MyContainer.java:1: MyContainer is not abstract and does not override abstract method addClass(java.lang.Class) in Container

If I add a type to the Container interface in MyContainer (such as <Object>), I don't get the error.

The problem is I'm introducing the type parameter to Container, which is part of the public API, so for compatibility, I can't have all implementing classes unable to compile.

Anyone have any ideas? Is it a type erasure issue? Is there a workaround?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

穿透光 2024-10-02 16:21:05

我认为问题在于,如果您在类声明中的任何位置使用原始类型,那么您就选择了退出泛型。所以这会起作用 - 请注意参数的变化。

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

来自 JLS 的第 4.8 节

超类(分别是
原始类型的超级接口)是
超类的删除
其任何一个的(超级接口)
参数化调用。

我相信这是相关的位... Container.addClass(Class> clazz) 的删除是addClass(Class clazz)< /代码>。

但是,是的,基本上除非这是真正的遗留代码,否则您应该将类​​型参数引入接口视为重大更改。

I think the problem is that if you use raw types anywhere in the class declaration, you're sort of opting out of generics. So this will work - note the parameter change.

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

From section 4.8 of the JLS:

The superclasses (respectively,
superinterfaces) of a raw type are the
erasures of the superclasses
(superinterfaces) of any of its
parameterized invocations.

I believe that's the relevant bit... the erasure of Container<T>.addClass(Class<?> clazz) is addClass(Class clazz).

But yes, basically unless this is genuine legacy code, you should regard introducing a type parameter into an interface as a breaking change.

〆凄凉。 2024-10-02 16:21:05

如果 修复了它,则摆脱它:

public void addClass(Class clazz) {}

错误消息不是很具有描述性:

名称冲突:MyContainer 类型的方法 addClass(Class) 与 Container 类型的 addClass(Class) 具有相同的擦除功能,但不会覆盖它

这意味着当类型被擦除时,两个方法都是相同的,但子类方法不会实际上并没有实现/覆盖超类/接口中的一个。这没有多大意义,我认为这是因为您选择不在子类中使用泛型,您必须坚持这一点(而不是对 Class 进行参数化)

Getting rid if the <?> fixes it:

public void addClass(Class clazz) {}

The error message is not very descriptive:

Name clash: The method addClass(Class) of type MyContainer has the same erasure as addClass(Class) of type Container but does not override it

This would mean that both your methods are the same when their types are erased, but the subclass method does not actually implement/override the one from the superclass/interface. This does not make much sense, and I would assume that it's because you have chosen not to use generics in your subclass, you have to stick to that (and not perameterize Class)

星星的軌跡 2024-10-02 16:21:05

如果您的类使用泛型,那么一个简单的解决方案是这样做:

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) {}
}

If your class uses Generics then a simple solution would be to do this :

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

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

Or if you already know the type of Container you have,

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

If your class doesn't use Generics (pre 1.5) then you can't have the <?> part. So there won't be any real problem here.

class MyContainer implements Container {
    public void addClass(Class clazz) {}
}
再可℃爱ぅ一点好了 2024-10-02 16:21:05

按如下方式实现您的接口应该可以工作(根据类型擦除):

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

Implementing your interface as follows should work (as per type erasure):

public class MyContainer implements Container {
    public void addClass(Class clazz) {}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文