I have a class heirarchies defined as follows:
class ClassA{}
class ClassB extends ClassA{}
class BaseClass
{
public <T extends ClassA> T method1(){ return null; }
public <T extends ClassA> T method2(T param1){ return null; }
}
I want to extend the above BaseClass and override the implementations of method1
and method2
, but I'm struggling with the method signature in the DerivedClass. Here's what I tried:
class DerivedClass extends BaseClass
{
@Override
public ClassB method1() {return new ClassB();}
@Override
public ClassB method2(ClassB param1) {return new ClassB();}
}
For method1
, I get the warning:
Type safety: The return type ClassB for method1() from the type DerivedClass needs unchecked conversion to conform to T from the type BaseClass
For method2
, I get the following error:
The method method2(ClassB) of type DerivedClass must override or implement a supertype method
How do I resolve this?
Edit: I had to refactor the design and put the generic type on the BaseClass
instead of each individual methods, so that such scenario doesn't occur.
CodePudding user response:
This method will works.
public class BaseClass<T extends ClassA> {
public T method1() {
return null;
}
public T method2(T param1) {
return null;
}
}
public class DerivedClass extends BaseClass<ClassB> {
@Override
public ClassB method1() {
return new ClassB();
}
@Override
public ClassB method2(ClassB param1) {
return new ClassB();
}
}
CodePudding user response:
The first warning is because JVM, due to type erasure cannot know whether the ClassB
is proper (does it extend ClassA
) and because there is a risk that some exception will be throw it warns you. To fix this you can add SuppressWarnings
annotation over the method
@Override
@SuppressWarnings("unchecked")
public ClassB method1() {return new ClassB();}
The second thing is quite similar but now JVM cannot create proper type/method signature (please notice that return type is not included into signature in Java! Please also notice that public ClassA method2(ClassA param1)
method would not cause such error).
To solve this you need to make compiler sure that the overridden method will have proper signature and to do this you need to move the generic type declaration on the class level
class BaseClass <T extends ClassA>
then extend this class with proper type
class DerivedClass extends BaseClass<ClassB> {
@Override
public ClassB method1() { // notice that you don't need Suppress annotation anymore
return new ClassB();
}
@Override
public ClassB method2(ClassB param1) {
return new ClassB();
}
}
Now the compiler is able to check whether used type is in bound or not
class ClassC {}
class DerivedClass extends BaseClass<ClassC> {
// ERROR: Type parameter 'com.mantkowicz.example.ClassC' is not within its bound
Read more here: