这是如何在内部发生的?使用什么机制? JNI,反思还是别的什么?编译器是否包含extends
子句?
不完全正确。
如果它们尚未扩展另一个类,则所有类都扩展Object,但有一个例外:java.lang.Object
本身不扩展任何类。
如果代码没有指定另一个超类,编译器会将超类java.lang.Object
嵌入到类文件中。
你甚至可以自己看看,如果用你喜欢的编辑器打开.class
文件,你可以看到嵌入在二进制数据中的字符串java/lang/Object
。
(您可以编译一个非常简单的源文件,如public class A { }
来观察这个最好)
这是一个关于java编译器内部的有趣问题。我找到了一个文档列表,提供了javac [1][2][3][4]的高级视图。像OpenJdk这样的特定实现的源代码也可以在网上找到[source]。
编译包括3个高级步骤[5]:
我编写了一些代码来使用Compiler Tree API来测试这些步骤,该API为javac提供了一个接口。
static class TestFileObject extends SimpleJavaFileObject {
public TestFileObject() {
super(URI.create("Test.java"), JavaFileObject.Kind.SOURCE);
}
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return "class Test { private int x; }";
}
}
public static void main(String[] args) throws IOException {
JavacTool tool = JavacTool.create();
JavacTask task = tool.getTask(null, null, null, null, null,
com.sun.tools.javac.util.List.of(new TestFileObject()));
// Step 1, Parse
Iterator<? extends CompilationUnitTree> trees = task.parse().iterator();
// Step 3, Analyze
// Iterator<? extends Element> elements = task.analyze().iterator();
// Step 3, Generate
// Iterator<? extends JavaFileObject> files = task.generate().iterator();
while(trees.hasNext()) {
CompilationUnitTree cu = trees.next();
System.out.println(cu.getTypeDecls());
}
}
使用步骤1运行上述代码显示以下输出:
class Test {
private int x;
}
因此AST不包含对java.lang.Object
的引用。接下来,我取消注释“Step 3,Analyze”并使用生成的输出重新运行我的代码:
class Test {
Test() {
super();
}
private int x;
}
请注意,在此步骤中添加了Test()
构造函数和super()
,这也对应于步骤3 [5]的解释:
在分析树时,可以找到成功编译所需的类的引用,但是没有明确指定用于编译。
最后,我取消注释Step 3, Generate
,它创建了Test.class
文件。调用javap -c Test.class
,生成的字节码是流下的:
class Test {
Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
}
所以我的结论是字节码生成步骤添加了java.lang.Object
相关逻辑。