Java - Overriding return type of extended interface when return type uses generics for own method parameter types
A basic idea is now to change this generic return type from GenericType in Interface A into GenericType in Interface A1
This is not possible, because Java Generics are invariant. [1]
As you found out, you cannot have an interface declaring a method that returns GenericType<Object>
and in a sub interface override the method to return GenericType<String>
: The latter return type is not a subtype of the former. And for good reason!
You tried to
extend indirectly the same interface with different generic types. This is unfortunately not allowed.
There is no way this could possibly work: E.g. what should be the type of E
in public E set(int index, E element)
in a class that implemented both List<String>
and List<Object>
? Your subclassed interface would have to produce a similar hybrid: The return value of getAGenericType
in the sub interface would have to implement both the GenericType<String>
and the GenericType<Object>
interface. And as we saw, this is impossible.
The compiler does not know what you are going to do with the type parameter in GenericType
(although it theoretically could find out, it doesn't). If you had a variable of type GenericType<String>
and assigned a GenericType<Object>
to it, you may very well end up putting a Long
instance where a String
is expected, and get a ClassCastException
where you won't expect one.
In the doSomethingWith
method of your variable GenericType<? extends Object> aGenericType2
you can pass one thing: null
. null
is the only object reference that has a subtype of ? extends Object
. The lower bound type of ? extends Object
is the null type, which cannot be expressed in Java, and only implicitly exists as the type of the null
reference.
[1] http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Java
I don't know if this is what you are expecting, but you can declare your interface something like:
public interface Interface <K extends Object> { ... }
While your class might look like:
public class InterfaceImpl implements Interface<String> { ... }
@Override annotation:
When overriding a method, you might want to use the @Override annotation that instructs the compiler that you intend to override a method in the superclass. If, for some reason, the compiler detects that the method does not exist in one of the superclasses, it will generate an error.
With this annotation you cannot change return type of function.
If you want to override return type, just make interface A more abstract, add generic to this interface:
public interface InterfaceA<T> {
public GenericType<T> getAGenericType();
}
Sample about overriding a generic method in a generic class.