方法调用
让我们看一下实际上是如何调用默认的方法的。如果你不熟悉这个问题,那么你可能有兴趣阅读一下Rebel实验室有关Java字节的报告。
从客户端代码的视角来看,默认的方法仅仅是常见的虚拟方法。因此名字应该是虚拟扩展方法。因此对于把默认方法实现为接口的简单例子类来说,客户端代码将在调用默认方法的地方自动调用接口。
A clazz = new Clazz();
clazz.foo(); // invokeinterface foo()
Clazz clazz = new Clazz();
clazz.foo(); // invokevirtual foo()
如果默认方法的冲突已经解决,那么当我们修改默认方法并指定调用其中一个接口时候,invokespecial将给我们指定具体调用哪个接口的实现。
public class Clazz implements A, B {
public void foo(){
A.super.foo(); // invokespecial foo()
}
}
下面是javap的输出:
public void foo();
Code:
0: aload_0
1: invokespecial #2 // InterfaceMethod A.foo:()V
4: return
正如你看到的:invokespecial指令用来调用接口方法foo()。从字节码的视角来看,这仍是新鲜的事情,因为以前你只能通过指向一个类(父类)的而不是指向一个接口的super来调用方法。