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

前端之家收集整理的这篇文章主要介绍了java – 类#getDeclaredMethods()返回继承的方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
参见英文答案 > getDeclaredMethods() behaving differently in Java 7 vs. Java 81个
考虑下一个代码
interface A {
    A setX(Object x);
    A setY(Object y);
}

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

如果您尝试将B.class.getDeclaredMethods()与jdk8一起使用
你会得到下一个方法

公共抽象B B.setX(java.lang.Object)和
public default A B.setX(java.lang.Object)

Javadoc说Class#getDeclaredMethods()只返回DECLARED方法,那么为什么返回2个方法呢?如果有人有解释,为什么第二种方法有’默认’修饰符?

我应该发布一个bug报告吗?
这个问题非常接近to this one,但影响版本是jdk6,对于jdk7,它工作正常(返回单个方法)

解决方法

我不会说这是一个错误.当您的B接口由javac编译时,它会添加一个返回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的默认实现,在这种情况下,需要自动生成的桥接方法来正确地将调用分派给该实现.

猜你在找的Java相关文章