Java 可协变的返回类型(Covariant return types )

可协变的返回类型(Covariant return types )

可协变的返回类型 :允许子类将覆盖方法的返回类型定义为原返回类型的子类型。

在Java 1.5 之前,在覆盖一个方法时,子类方法的方法名,参数类型和返回类型必须和超类的被覆盖方法完全一致,不允许改变被覆盖方法的返回类型。但是现在,Java 1.5 之后,子类在覆盖返回类型不是基本类型的方法时,允许将返回类型改为原类型的子类型。

如何实现的

先看一个例子

class B {
    public B foo() {
    	...
        return new B();
    }

}

class C extends B {
    @Override
   public C foo() {
   		...
        return new C();
    }
    
}

    public static void main(String[] args) {
        Class<?> cls = C.class;
        Method[] methods = cls.getDeclaredMethods();
        for (Method m : methods) {
            System.out.println(m + (m.isSynthetic() ? " isSynthetic" : "   noSynthetic") + (m.isBridge() ? "  isBridge" : "  noBridge"));
        }
    }
    // 输出
    public reflectionTest.C reflectionTest.C.foo()   noSynthetic  noBridge
	public reflectionTest.B reflectionTest.C.foo() isSynthetic  isBridge

通过反射我们发现类C中出了方法 public C foo() ,还有方法 public Bfoo(),并且方法 public B foo() 是合成的桥方法。为什么类C能有两个方法名称相同并且参数类型也相同的方法呢?

尽管在Java 中,方法的签名只包括方法名称和方法的参数类型,不允许基于返回类型的方法重载(即,方法名称和类型参数都相同,方法返回类型不同)。但是在JVM是允许基于返回类型的方法重载的,JVM通过方法的参数类型和返回类型进行方法调用(区分不同方法)。所以在JVM中,一个类可以拥有多个仅仅是返回类型不同的方法。

为了实现可协变的返回类型,Java会隐式合成新的方法。
实际上javac生成的代码类似于这样:

class C extends B{
    public C foo() {
       // your code from the source file
    }
    // javac generated method in the .class file
    public B foo() {
       // 调用另一个foo()方法
    } 
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值