问题

覆盖的方法可以有不同的返回类型吗?


#1 热门回答(137 赞)

Java支持用于重写方法的*协变返回类型。这意味着重写的方法可能具有特定于amorespeclic的返回类型。也就是说,只要新的返回类型可以分配给你重写的方法的返回类型,就允许它。

例如:

class ShapeBuilder {
    ...
    public Shape build() {
    ....
}

class CircleBuilder extends ShapeBuilder{
    ...
    @Override
    public Circle build() {
    ....
}

这在section 8.4.5 of the Java Language Specification中指定:

如果返回类型是引用类型,则返回类型可能因覆盖彼此的方法而异。返回类型可替代性的概念支持协变返回,即返回类型到子类型的特化。返回类型为R1的方法声明d1是返回类型 - 可替代另一个返回类型为R2的方法d2,当且仅当以下条件成立时:如果R1为空,则R2为空。如果R1是基本类型,则R2与R1相同。如果R1是引用类型,则:R1是R2的子类型,或者R1可以通过未经检查的转换(第5.1.9节)或R1 = | R2 |转换为R2的子类型。

("| R2 |"指的是R2的擦除,如§4.6 of the JLS中所定义。)
*在Java 5之前,Java hadinvariantreturn类型,这意味着方法覆盖的返回类型需要与被覆盖的方法完全匹配。


#2 热门回答(18 赞)

是的,如果他们返回一个子类型。这是一个例子:

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 {
    }
}

此代码编译并运行。


#3 热门回答(18 赞)

是的,它可能有所不同,但它们有一些限制。

在Java 5.0之前,当你重写方法时,参数和返回类型必须完全匹配。在Java 5.0中,它引入了一个名为协变返回类型的新工具。你可以使用相同的签名覆盖方法,但返回返回的对象的子类。换句话说,子类中的方法可以返回一个对象,该对象的类型是由超类中具有相同签名的方法返回的类型的子类。


原文链接