Java Covariant Return Types
In this page:
What is a Covariant Return Type?
A covariant return type lets an overriding method in a subclass declare a more specific return type than the parent method it's overriding, as long as that more specific type is itself a subtype of the parent's declared return type.
Example: What is a Covariant Return Type?
class Animal {}
class Dog extends Animal {}
class AnimalShelter {
Animal adopt() { return new Animal(); }
}
class DogShelter extends AnimalShelter {
@Override
Dog adopt() { return new Dog(); } // more specific return type
}
public class Main {
public static void main(String[] args) {
System.out.println(new DogShelter().adopt() instanceof Dog);
}
}
Login to try C/C++/Java/PHP code in the editor
Covariant Returns with Custom Classes
This is especially useful for factory-style methods: a parent class's clone()-like method might return the general parent type, while a subclass override can return its own specific subclass type directly, giving callers a more precise type without any manual casting.
Example: Covariant Returns with Custom Classes
class Shape {
Shape create() { return new Shape(); }
}
class Circle extends Shape {
@Override
Circle create() { return new Circle(); } // factory-style covariant return
}
public class Main {
public static void main(String[] args) {
Circle c = new Circle().create();
System.out.println(c instanceof Circle);
}
}
Login to try C/C++/Java/PHP code in the editor
Type Safety Benefits
Without covariant returns, callers would need an explicit downcast to get back the more specific type they know they're actually receiving — covariant returns let the compiler track that precision automatically and catch type errors earlier.
Example: Type Safety Benefits
class Animal {}
class Dog extends Animal {}
class DogShelter {
Dog adopt() { return new Dog(); }
}
public class Main {
public static void main(String[] args) {
Dog d = new DogShelter().adopt(); // no downcast needed
System.out.println(d);
}
}
Login to try C/C++/Java/PHP code in the editor
Standard Library Covariants
Several places in the standard library use covariant returns, most notably Object.clone(), where subclasses commonly override clone() to return their own type instead of the generic Object the parent method declares.
Example: Standard Library Covariants
class Point implements Cloneable {
int x = 5;
@Override
public Point clone() {
try {
return (Point) super.clone(); // covariant: returns Point, not Object
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
public class Main {
public static void main(String[] args) {
Point p = new Point();
Point copy = p.clone();
System.out.println(copy.x);
}
}
Login to try C/C++/Java/PHP code in the editor
Rules for Covariant Returns
The rule only applies to reference types, not primitives — a double-returning method can't be overridden to return an int, even though int values can convert to double, because covariance is strictly about subtype relationships between reference types.
Example: Rules for Covariant Returns
class Base {
Object getValue() { return "base"; }
}
class Derived extends Base {
@Override
String getValue() { return "derived"; } // String is a subtype of Object
}
public class Main {
public static void main(String[] args) {
System.out.println(new Derived().getValue());
}
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: