为什么接口根据类文件格式扩展Object?

为什么JVM规范声明接口必须具有java/lang/Objectsuper_class ,即使接口不扩展java/lang/Object

我特别指的是JVM规范的§4.1 ,它说:

对于接口,super_class项的值必须始终是constant_pool表的有效索引。 该索引处的constant_pool条目必须是表示Object类的CONSTANT_Class_info结构。

但是在JLS的第9.2节中,它说接口不扩展Object。 而是声明一个隐式创建的抽象方法,它匹配Object类中的每个公共方法:

如果接口没有直接的超接口,则接口隐式声明一个公共抽象成员方法m,其中包含签名s,返回类型r和throws子句t,对应于每个公共实例方法m,其中包含签名s,返回类型r和throws子句t在Object中声明,除非接口显式声明具有相同签名,相同返回类型和兼容throws子句的方法。

如§9.2中所述 :

如果接口没有直接的超接口,则接口隐式声明一个公共抽象成员方法m,其中包含签名s,返回类型r和throws子句t,对应于每个公共实例方法m,其中包含签名s,返回类型r和throws子句t在Object中声明,除非接口显式声明具有相同签名,相同返回类型和兼容throws子句的方法。

因此,我们看到,虽然没有直接超接口的接口没有显式扩展Object但仍然在内部有一个Object类的链接,因为编译器使用它来插入具有相同签名和返回类型的抽象方法,并将throws子句作为接口内Object类中的公共方法。 这就是为什么对于接口,super_class项的值必须始终是constant_pool表的有效索引。 该索引处的constant_pool条目必须是表示Object类的CONSTANT_Class_info结构。 这就是接口引用变量可以成功调用公共实例方法的原因,例如Object toString()方法。 例如,考虑下面给出的代码:

 interface MyInterface {} public class InterfaceTest implements MyInterface { public static void main(String[] args) { MyInterface mInterface = new InterfaceTest(); System.out.println(mInterface.toString());//Compiles successfully. Although toString() is not declared within MyInterface } } 

即使toString()方法(这是Object的方法)未在MyInterface声明,上面的代码也能成功编译。 以上代码在我的系统上提供以下输出:

 InterfaceTest@1ba34f2 

输出可能因系统而异。

您在JVM规范中看到的基本上是JLS指定的行为的具体实现 – 就像类实现接口并具有实现细节一样。