类#getDeclaredMethods()返回继承的方法



考虑下一个代码:

interface A {
    A setX(Object x);
    A setY(Object y);
}
interface B extends A {
    B setX(Object x);
}

如果您尝试使用B.class.getDeclaredMethods()与jdk8您将获得以下方法:

public abstract B B. setx (java.lang.Object) andB.setX(java.lang.Object)

Javadoc说Class#getDeclaredMethods()只返回声明的方法,那么为什么返回2个方法?如果有人解释了为什么第二个方法有'default'修饰符?

我应该发布一个bug报告吗?这个问题非常接近这个,但影响版本是jdk6和jdk7它工作得很好(返回单一方法)

我不会说这是一个bug。在javac编译B接口时,增加了一个合成桥接方法,返回A。您可以通过检查javap输出看到这一点:

$ javap -c B
Compiled from "B.java"
interface B extends A {
  public abstract B setX(java.lang.Object);
  public A setX(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: invokeinterface #1,  2          // InterfaceMethod     setX:(Ljava/lang/Object;)LB;
       7: areturn
}

在Java 1.7中当然没有这样的方法,因为在Java中不可能创建默认方法。因此,在1.7中编译时,您将得到以下内容:

$ javap -c B
Compiled from "B.java"
interface B extends A {
  public abstract B setX(java.lang.Object);
}
然而,在Java 1.8中,这个额外的方法实际上是在字节码中声明的,所以getDeclaredMethods()正确地返回它。对于这个额外的方法,isBridge()isSynthetic()调用将返回true,所以如果你不喜欢它,你可以基于此过滤掉它。

桥方法对于正确实现协变返回类型很有用,因为JVM不知道这个特性。它们对于分派对具有协变返回类型的方法的虚调用是必需的。Java 1.8中出现的新桥接方法有助于支持默认方法的协变返回类型。子接口可以定义setX的默认实现,在这种情况下,需要自动生成的桥接方法来正确地调度对该实现的调用。

相关内容

  • 没有找到相关文章