简体   繁体   English

为什么Java会在编译时生成多个.class文件?

[英]Why does Java generate Multiple .class files on compilation?

In Java, on compilation we get a .class file for each class( including nested classes and interfaces) defined in the source file. 在Java中,在编译时,我们为源文件中定义的每个类(包括嵌套类和接口)获取.class文件。

What is the reason for this multiple .class file generation? 生成多个.class文件的原因是什么?
Is it for simplifying the reusablity of the class? 是为了简化课堂的重复性吗?
Why not generate one .class for one .java file? 为什么不为一个.java文件生成一个.class?

The JVM needs to be able to find the code for a given class, given its name. JVM需要能够找到给定类的代码,并给出其名称。 If there's potentially no relationship between the source filename and the code filename, and you want the code filename to be based on the source filename, how would you expect it to load the code? 如果源文件名和代码文件名之间可能没有关系,并且您希望代码文件名基于文件名,那么您希望它如何加载代码?

As an example: suppose I were to compile Foo.java which contains class Bar. 举个例子:假设我要编译包含类Bar的Foo.java。

Another class then refers to Bar, so the JVM needs the code for it... how would you suggest it finds the file? 然后另一个类引用Bar,所以JVM需要它的代码......你会如何建议找到该文件?

Note that in .NET there's a separate of unit of deployment called the assembly - and a reference to a type includes the assembly name as well, but that's slightly different from what you were proposing. 请注意,在.NET中,有一个单独的部署单元称为程序集 - 对类型的引用也包括程序集名称,但这与您提议的略有不同。

In response to @Jon Skeet's rhetorical question: 回应@Jon Skeet的修辞问题:

Another class then refers to Bar, so the JVM needs the code for it... how would you suggest it finds the file? 然后另一个类引用Bar,所以JVM需要它的代码......你会如何建议找到该文件?

Suppose (hypothetically) that the Java classfile format represented nested / inner classes by embedding them in the classfile for the outermost class. 假设(假设)Java类文件格式通过将它们嵌入最外层的类文件中来表示嵌套/内部类。 The binary name for the Bar is " Lsome/pkg/Foo$Bar; ". Bar的二进制名称是“ Lsome/pkg/Foo$Bar; ”。 The class loader could split the name at the " $ " character, use the first part to locate the classfile for Foo, and then navigate to the embedded Bar class representation. 类加载器可以将名称拆分为“ $ ”字符,使用第一部分找到Foo的类文件,然后导航到嵌入的Bar类表示。

I think that the real reason that inner/nested classes have separate classfiles is historical. 我认为内部/嵌套类具有单独的类文件的真正原因是历史性的。 IIRC, Java 1.0 did not support nested or inner classes, and hence the corresponding classfile formats did not need to deal with them. IIRC,Java 1.0不支持嵌套或内部类,因此相应的类文件格式不需要处理它们。 When Java 1.1 was created (supporting inner/nested classes), Sun wanted the classfile format to be compatible with the classfiles produced by the Java 1.0 compiler. 当创建Java 1.1(支持内部/嵌套类)时,Sun希望类文件格式与Java 1.0编译器生成的类文件兼容。 So they chose to implement inner / nested classes as separate classfiles, using the reserved " $ " character in the binary classname. 因此,他们选择使用二进制类名中的保留“ $ ”字符将内部/嵌套类实现为单独的类文件。

A second possible reason is that the flat format simplifies class loading compared to a hypothetical embedded format. 第二个可能的原因是,与假设的嵌入格式相比,平面格式简化了类加载。

And finally, there was (and still is) no compelling reason for them NOT to use a flat file format. 最后,他们(并且仍然)没有令人信服的理由不使用平面文件格式。 It maybe creates some minor head-scratching when some programmer wants to load inner classes using Class.forName() but that is pretty rare occurrence ... and the solution is straight-forward. 当一些程序员想要使用Class.forName()加载内部类时,它可能会产生一些小问题,但这种情况很少发生......并且解决方案是直截了当的。

That's is a design decision regarding a compilation unit, made by the developers. 这是关于编译单元的设计决策,由开发人员制作。 Compiled classes are usually combined in a jar file. 编译类通常组合在一个jar文件中。

Extract from Java Language Spec Java语言规范中提取

7.3 Compilation Units CompilationUnit is the goal symbol (§2.1) for the syntactic grammar (§2.3) of Java programs. 7.3编译单元CompilationUnit是Java程序的语法语法(第2.3节)的目标符号(第2.1节)。

Types declared in different compilation units can depend on each other, circularly. 在不同编译单元中声明的类型可以循环相互依赖。 A Java compiler must arrange to compile all such types at the same time. Java编译器必须安排同时编译所有这些类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM