假设以下现实生活中的代码结构:
interface I {
I m();
}
abstract class A implements I {
@Override
public abstract A m();
abstract class B extends A {
}
}
为 B 生成的字节码是
abstract class A$B extends A {
<some stuff>
public I m(); //bridge method
Code:
0: aload_0
1: invokespecial #2 // Method A.m:()LA;
4: areturn
}
注意invokespecial 指令指向抽象方法Am() 的使用。在我看来,这必须在运行时根据 JVM 8 规范在invokespecial上导致 AbstractMethodError :
如果以下所有条件都为真,则令 C 为当前类的直接超类。
因此,在我们的示例中,A 将被选为 C。
要调用的实际方法由以下查找过程选择。
1) 如果 C 包含与已解析方法具有相同名称和描述符的实例方法的声明,那么它就是要调用的方法。
所以JVM会选择Am()。
但是运行时异常部分指出:
否则,如果查找过程的第 1 步、第 2 步或第 3 步选择了一个抽象方法,invokespecial 将抛出一个 AbstractMethodError。
因此调用该方法将导致错误。
我只是想知道,为什么 Java 编译器会生成这样的被判失败的字节码?
PS 我猜测上面的桥接方法根本不会被调用,因为 AB 类的最终实现者将覆盖它。但是接下来就出现了下面的问题:java生成这个桥接方法是为了什么目的?