It is not possible to compile a class that implements an interface without a type parameter

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 classes:

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

If I add a type to the Container container in MyContainer (e.g. <Object> ), I will not get an error.

The problem is that I introduced the type parameter in Container, which is part of the public API, so for compatibility I cannot use all implementation classes that cannot be compiled.

Does anyone have any idea? Is this a type erase problem? Is there any workaround?

+6
java override generics type-erasure type-parameter
source share
4 answers

I think the problem is that if you use raw types anywhere in the class declaration, you are kind of giving up generics. So this will work - pay attention to changing the parameter.

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

From section 4.8 JLS :

Superclasses (respectively, superinterfaces) of the original type are the erasure of superclasses (superinterfaces) of any of the parameterized calls.

I believe the corresponding bit ... erasing the Container<T>.addClass(Class<?> clazz) is addClass(Class clazz) .

But yes, in principle, if this is not genuine legacy code, you should consider introducing the type parameter into the interface as a violation.

+7
source share

How to get rid if <?> Fixes it:

 public void addClass(Class clazz) {} 

The error message is not very descriptive:

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

This would mean that both methods are the same when their types are erased, but the subclass method does not actually implement / cancel one of the superclass / interface. This doesn't make much sense, and I would suggest that this is because you decided not to use generics in your subclass, you should stick with this (rather than perameterize Class )

+3
source share

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 that you have,

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

If your class does not use Generics (pre 1.5), then you cannot have the <?> Part. So there will be no real problem here.

 class MyContainer implements Container { public void addClass(Class clazz) {} } 
+3
source share

Implementing your interface as follows should work (like erasing styles):

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

All Articles