【发布时间】:2009-08-28 04:39:12
【问题描述】:
当您在 Java 中创建用户定义的类时,您没有将其指定为扩展 Object。但是这个类仍然是一个对象。这是如何运作的? javac或JVM如何将一个类的所有属性注入到用户定义的类中?
【问题讨论】:
标签: java inheritance compiler-construction
当您在 Java 中创建用户定义的类时,您没有将其指定为扩展 Object。但是这个类仍然是一个对象。这是如何运作的? javac或JVM如何将一个类的所有属性注入到用户定义的类中?
【问题讨论】:
标签: java inheritance compiler-construction
如果你实际上没有写extends Object,编译器会为你插入它。
编辑:显然我对是否真的有代码插入造成了一些混乱。我自己不太确定,所以我做了一个小实验:在文件 test.java 中创建以下类:
public class test {}
编译,然后运行
javap -c test
反汇编字节码。看看结果:
编译自“test.java”
公共类测试扩展 java.lang.Object{
公共测试();
代码:
0:aload_0
1:调用特殊#1; //方法 java/lang/Object."":()V
4:返回
}
所以是的,编译器确实实际上将extends java.lang.Object(或等效的字节码)插入到类中。
【讨论】:
java/lang/Object 类没有超类。在这种情况下,超类字段设置为 0 而不是常量池条目。
所有 java 类都隐式扩展 java.lang.Object。来自documentation:
类Object 是类层次结构的根。每个类都有Object 作为超类。所有对象,包括数组,都实现了这个类的方法。
这里还有一个指向JVM spec 的链接:
标准类Object 是所有其他类的超类(第 2.8.3 节)。 Object 类型的变量可以保存对任何对象的引用,无论它是类的实例还是数组。所有类和数组类型都继承了 Object 类的方法。
【讨论】:
嗯,这可能是一个油嘴滑舌的答案(我最喜欢的那种),但如果你指定一个父类,它可能会以同样的方式派生一个类。如果您编写编译器,您不就是这样做的吗?
【讨论】:
这是因为所有用户定义的类型都隐式继承自 Object。
【讨论】:
如果说 JVM 将属性或方法“注入”到类中,这听起来像是编译器或运行时在事后所做的事情,就好像 .class 文件不同一样。实际上,所发生的只是当解析器发现您没有在extends 中包含任何基类时,它只是假装您明确指定了Object。从那时起,编译器将其视为您自己输入的一样,并且 JVM 不知道您在源代码中做了什么或没有指定什么。
【讨论】: