开发者

Cannot compile a class which implements an interface without type parameter

开发者 https://www.devze.com 2023-01-18 20:49 出处:网络
I have the following test code: public interface Container<I> { public void addClass(Class<?> clazz);

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 开发者_JAVA技巧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?


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.


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)


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


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

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

精彩评论

暂无评论...
验证码 换一张
取 消