In this tutorial, we’re going to have a closer look at the covariant return type in Java. Before examining covariance from the return type’s point of view, let’s see what that means.
Covariance can be considered as a contract for how a subtype is accepted when only the supertype is defined.
Let’s consider a couple of basic examples of covariance:
List<?
extends
Number> integerList =
new
ArrayList<Integer>();
List<?
extends
Number> doubleList =
new
ArrayList<Double>();
So covariance means, we can access specific elements defined via their supertype. However, we aren’t allowed to put elements into a covariant system, since the compiler would fail to determine the actual type of the generic structure.
The covariant return type is – when we override a method – what allows the return type to be the subtype of the type of the overridden method.
To put this into practice, let’s take a simple _Producer _class with a produce() method. By default, it returns a _String _as an _Object _to provide flexibility for the child classes:
public
class
Producer {
public
Object produce(String input) {
Object result = input.toLowerCase();
return
result;
}
}
As a result of the _Object _as a return type, we can have a more concrete return type in the child class. That will be the covariant return type and will produce numbers from character sequences:
public
class
IntegerProducer
extends
Producer {
@Override
public
Integer produce(String input) {
return
Integer.parseInt(input);
}
}
#java