参见英文答案 >
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的默认实现,在这种情况下,需要自动生成的桥接方法来正确地将调用分派给该实现.