【问题标题】:Two methods when implementing interface containing only one实现只包含一个接口时的两种方法
【发布时间】:2013-12-25 10:48:14
【问题描述】:

我创建了接口TwoMethods。源代码:

interface TwoMethods<T>
{
    public void method(T t);
}

然后我创建了实现这个接口的类,反汇编后我看到了 2 个方法。 类:

class A implements TwoMethods<A>
{
    @Override
    public void method(A a) {}
}

拆卸后:

class A implements TwoMethods<A> {
   A();
   public void method(A); //first
   public void method(java.lang.Object); //second
}

Comparable 接口类似。为什么当我创建参数化接口时我有 2 种方法。总是,当我使用参数时?我还有 Object 作为参数的方法?

【问题讨论】:

    标签: java generics interface type-erasure java-bridge-method


    【解决方案1】:

    method(java.lang.Object) 被称为桥接方法,它是由于编译时类型擦除而生成的。

    Effects of Type Erasure and Bridge Methods

    【讨论】:

      【解决方案2】:

      如果我们查看接口 TwoMethods 字节码,我们会看到实际的方法是

      public abstract method(Ljava/lang/Object;)V
      

      即关于类型参数的字节码级别信息不存在,类型被删除,JVM 根本不知道泛型,类型参数被替换为Object 或者如果T extends XX 替换。所以从JVM的角度来看

      class A implements TwoMethods<A> {
          public void method(A a) {
              ...
      

      method(A a) 不会覆盖接口方法,因为在字节码中它位于 method(Object obj) 中可以覆盖它。为了解决这个问题,编译器在 A 类中构建了一个隐式方法,即所谓的桥接方法

      public void method(Object obj) {
           method((A)obj);
      }
      

      仅在字节码中可见。现在为这段代码

      A a = new A();
      TwoMethods<A> tm = a;
      tm.method(a);
      

      编译器会将tm.method(a) 替换为对桥的调用

         INVOKEINTERFACE test/TwoMethods.method(Ljava/lang/Object;)V
      

      这会将呼叫重定向到A.method(A a);

      【讨论】:

        猜你喜欢
        • 2020-02-20
        • 1970-01-01
        • 2022-08-17
        • 2015-11-06
        • 2017-12-18
        • 2013-12-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-10
        相关资源
        最近更新 更多