Can overridden methods differ in return type?
Solution 1:
Java supports* covariant return types for overridden methods. This means an overridden method may have a more specific return type. That is, as long as the new return type is assignable to the return type of the method you are overriding, it's allowed.
For example:
class ShapeBuilder {
...
public Shape build() {
....
}
class CircleBuilder extends ShapeBuilder{
...
@Override
public Circle build() {
....
}
This is specified in section 8.4.5 of the Java Language Specification:
Return types may vary among methods that override each other if the return types are reference types. The notion of return-type-substitutability supports covariant returns, that is, the specialization of the return type to a subtype.
A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2, if and only if the following conditions hold:
If R1 is void then R2 is void.
If R1 is a primitive type, then R2 is identical to R1.
If R1 is a reference type then:
R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or
R1 = |R2|
("|R2|" refers to the erasure of R2, as defined in §4.6 of the JLS.)
* Prior to Java 5, Java had invariant return types, which meant the return type of a method override needed to exactly match the method being overridden.
Solution 2:
Yes it may differ but there are some limitations.
Before Java 5.0, when you override a method, both parameters and return type must match exactly. Java 5.0 it introduces a new facility called covariant return type. You can override a method with the same signature but return a subclass of the object returned.
In another words, a method in a subclass can return an object whose type is a subclass of the type returned by the method with the same signature in the superclass.
Solution 3:
Yes, if they return a subtype. Here's an example:
package com.sandbox;
public class Sandbox {
private static class Parent {
public ParentReturnType run() {
return new ParentReturnType();
}
}
private static class ParentReturnType {
}
private static class Child extends Parent {
@Override
public ChildReturnType run() {
return new ChildReturnType();
}
}
private static class ChildReturnType extends ParentReturnType {
}
}
This code compiles and runs.