Covariant Return Types in Java
As you already know, in Java, method overriding is a mechanism for providing new behavior for the superclass method in a subclass method.
Note that the terms subclass and child class in Java are used interchangeably, as are superclass and parent class. A subclass (or child class) inherits from a superclass (or parent class), allowing it to reuse or override the behaviors defined in the superclass.
Method overriding follows a set of specific rules. When you override a superclass method, the name and parameters of a subclass method have to be exactly the same as that of the superclass method. The situation with regards to the return type, however, is slightly different. The subclass method can return the same type as the superclass method or a subtype of that return type. This feature is known as the covariant return type.
How it works
Covariant return type allows you to narrow (but not widen) the return type of the overridden method, that is, to make it more specific.
The following picture demonstrates the covariance with respect to the type B. If the superclass method returns B then an overriding subclass method can return B, D or E, but not A, C or F.
Covariance with respect to the type B
Let's consider the following code:
class SuperType { }
class SubType extends SuperType { }
class A {
public SuperType getType() {
return new SuperType();
}
}
class B extends A {
@Override
public SubType getType() {
return new SubType();
}
}
In this example, the SubType
class inherits from SuperType
. The method getType
of A
returns an instance of SuperType
, but the overridden method getType
of the class B
(that extends A
) returns an instance of SubType
. There are no compile-time errors, this overriding method works perfect.
In the example shown below, we get a compiler error:
class A {
public SubType getType() {
return new SubType();
}
}
class B extends A {
@Override
public SuperType getType() {
return new SuperType();
}
}
Here, the method getType
of the class A
returns an instance of SubType
, while the overridden method getType
of the class B
returns an instance of SuperType
. It's not a covariant return type so this code does not compile.
Summary
Remember, when overriding a subclass method, the return type can be the same type or a subclass of the return type of a superclass method. Covariance is always changing down the hierarchy.
It is also important to note that the co-variant return types are possible only for non-primitive return types.