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

rli*_*rli 13 java 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("----------");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

 ---Derived---
public abstract BreakingInterfaces$Derived$DerivedFoo BreakingInterfaces$Derived.foo()
----------
Run Code Online (Sandbox Code Playgroud)

但是当使用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()
----------
Run Code Online (Sandbox Code Playgroud)

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

Hol*_*ger 15

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

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

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

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