如何使用桥接方法实现协变返回类型

时间:2018-06-15 07:01:04

标签: java generics bridge covariant-return-types

我目前正在研究java通用版,参考书籍#34; java generics和Maurice Naftalin 2006"的集合。

在返回类型的协变覆盖部分中,作者声明

enter image description here enter image description here

有人可以向我解释一下,实现是什么,即桥接方法中的代码是什么样的?桥接方法是否调用原始方法(即带有签名public Point clone()的方法)?

2 个答案:

答案 0 :(得分:1)

我建议你参考Oracle material关于它并进行一些测试以了解桥梁机制。

Bridge是一种超越覆盖方法能力的工件,它在Java 1.5之前的编译时是不变的。

  

Java 1.5支持协变返回类型。这是什么意思?之前   1.5,当覆盖超类方法时,覆盖方法的名称,参数类型和返回类型必须与覆盖方法完全相同   超类方法。据说覆盖方法是不变的   尊重参数类型和返回类型。

     

如果你改变任何参数类型,那么你并没有真正重写   方法 - 你实际上正在超载它。

桥是一座桥:所以它建立了一个链接。这是在具有原始返回类型的方法和具有协变返回类型的覆盖方法之间 所以是的,你是对的。

你想检查一下吗? 编译该类,然后反汇编它的源代码。

  

$ javap -c Point.class

你会得到类似的东西:

Compiled from "Point.java"
public class Point {
  public Point(int, int);
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."":()V
       4: aload_0
       5: iload_1
       6: putfield      #2                  // Field x:I
       9: aload_0
      10: iload_2
      11: putfield      #3                  // Field y:I
      14: return

  protected Point clone() throws java.lang.CloneNotSupportedException;
    Code:
       0: new           #4                  // class Point
       3: dup
       4: aload_0
       5: getfield      #2                  // Field x:I
       8: aload_0
       9: getfield      #3                  // Field y:I
      12: invokespecial #5                  // Method "":(II)V
      15: areturn

  protected java.lang.Object clone() throws java.lang.CloneNotSupportedException;
    Code:
       0: aload_0
       1: invokevirtual #6                  // Method clone:()LPoint;
       4: areturn
}

您可以在Object clone()Point clone()之间看到授权 当然,您不能编写代码,因为在编译时Java不允许基于返回类型的重载,但在运行时JVM可以使用编译类中的此功能。

答案 1 :(得分:0)

  

有人可以告诉我,实现是什么,即bridge方法中的代码是什么样的?

我们在此提供一个示例:类java.text.AttributeEntry包含一个bridge方法getKey()

  • 这是此方法的call graph

enter image description here

  • 这是此方法的decoded byte code

enter image description here

here列出了JDK中的所有bridge方法。在回顾了其中的一些内容之后,我们可能得出以下结论:

  • bridge只是在调用原始方法
  • 所以这就是 bridge
  • 的原因