getDeclaredMethods()在Java 7与Java 8中的表现不同

考虑以下小例子:

package prv.rli.codetest; import java.lang.reflect.Method; public class BreakingInterfaces { interface Base { BaseFoo foo(); interface BaseFoo { } } interface Derived extends Base { DerivedFoo foo(); interface DerivedFoo extends BaseFoo { } } public static void main(String[] args) { dumpDeclaredMethods(Derived.class); } private static void dumpDeclaredMethods(Class class1) { System.out.println("---" + class1.getSimpleName() + "---"); Method[] methods = class1.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } System.out.println("----------"); } } 

如果使用jdk1.7.0.55编译上面的示例,则输出为:

  ---Derived--- public abstract BreakingInterfaces$Derived$DerivedFoo BreakingInterfaces$Derived.foo() ---------- 

但是当使用jdk1.8.0.25时,输出是:

 ---Derived--- public abstract prv.rli.codetest.BreakingInterfaces$Derived$DerivedFoo prv.rli.codetest.BreakingInterfaces$Derived.foo() public default prv.rli.codetest.BreakingInterfaces$Base$BaseFoo prv.rli.codetest.BreakingInterfaces$Derived.foo() ---------- 

有谁知道,这是jdk1.8.0.25中的错误还是为什么公共默认方法重新出现在这里?

getDeclaredMethods()在这里表现正确,因为它告诉你它在类中找到了什么。 如果您输入使用Java 7目标(或较旧的编译器)编译的interface ,您将看到getDeclaredMethods()的Java 7实现的输出没有区别。

这是编译器的行为不同。 在Java 8中编译这样的子interface时,将生成一个不会为Java 7目标生成的桥接方法,因为它甚至不可能用于Java 7目标。

现在为接口生成桥接方法的原因是您通常拥有比接口更多的实现类,因此在接口中使用default桥接方法可以避免将该桥接方法添加到每个实现。 此外,如果只有一个abstract方法并且没有实现的桥接方法,它使得lambda类生成变得更加容易。

interface层次结构需要桥接方法但不提供default ,编译器必须使用LambdaMetafactory.altMetafactory而不是LambdaMetafactory.metafactory来生成代码,并指定所需的每个桥接方法。