考虑以下小例子:
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指定所需的每个桥接方法来生成代码.