Return Types & Covariant Return Types in Java

1. Returning Objects

A method can use a class as its return type.

public Number returnANumber() {
    return new ImaginaryNumber();
}

The returned object must be:

Example hierarchy:

Object
  ↑
Number
  ↑
ImaginaryNumber

Therefore:

Number method() {
    return new ImaginaryNumber();  // Valid
}

But:

Number method() {
    return new Object();           // Invalid
}

Because Object is a superclass of Number, not a subclass.


2. Covariant Return Type

When overriding a method, Java allows the overriding method to return a more specific type (subclass) than the original method.

class Animal {
    public Animal getAnimal() {
        return new Animal();
    }
}

class Dog extends Animal {

    @Override
    public Dog getAnimal() {
        return new Dog();
    }
}

Here:

Original method → Animal
Overridden method → Dog

Dog is a subclass of Animal, so this is valid.

This is called a covariant return type.

Covariant return type = an overridden method can return a more specific (subclass) type.


3. Interface as Return Type

An interface can also be used as a return type.

interface Animal {
}

class Dog implements Animal {
}

class Factory {
    public Animal createAnimal() {
        return new Dog();
    }
}

The returned object must implement the specified interface.

Quick Rule

Return type = Class
      ↓
Same class OR subclass

Return type = Interface
      ↓
Object must implement interface

Overriding method
      ↓
Can return a subclass
      ↓
Covariant return type