2017-10-18 175 views
1

我学会了here,即使这是最佳实践并且尽管大多数编译器要求您这样做,但它并不是严格要求在其包含的公共类之后命名的.class至少从语言规范的角度来看。.class文件的Java语言命名约定

我搜索了JLS和JVM规范,但无法找到本主题讨论的实际章节。对我而言,这个问题在之间根本没有被处理过

如果存在的话,Oracle官方文档可以确认或揭穿以下声明?

给予.class文件相同的名称,它们所包含的公共类 - 无论他们做的 - 简直是必须的,但根据JLS这不是严格的。从JLS的角度来看,编译器会选择是否设置这样的限制。

+0

我会用进一步引用出版物/著作该主题的章节或页码。 – Salvioner

+0

请注意,每个.java源可能有多个.class文件,即每个创建的内部类都有一个.class文件。对于匿名内部类,通常对于命名内部类的格式为'[toplevel_public_class] $ [inner_class] .class',对于匿名内部类格式为'[toplevel_public_class] $ [number] .class'“。我不知道这是一个规则还是一种标准的做法,但是.class文件并不总是完全匹配顶级类的名称(尽管它是名称的重要组成部分)。 – Thomas

+0

顺便说一句,我可能在这里是错误的,但从运行时的角度来看,文件名应该不重要,因为文件包含所有必要的信息。但是,具有匹配的文件名称使人类或基于文本的操作更容易(例如,尝试在jar中查找类以加载它),因为您不必扫描每个文件以找到正确的文件。对源文件的限制也可能主要是为了防止人们将其搞乱;) – Thomas

回答

2

这在JLS §13.1., The Form of a Binary解决:

程序必须编译要么成Java虚拟机规范的Java SE 8版指定的class文件格式,或者为可以表示通过用Java编程语言编写的类加载器映射到该格式。

所以你并不需要在所有提供的编译代码为.class文件,只要你有能力加载您的代码表示的类加载器的实现。请注意,在这个级别上,例如当将映射数据传递给ClassLoader.defineClass时,类文件的文件名根本不存在。这两个规范JLS和JVM都一致地使用术语“类文件”作为“类文件格式中的字节序列”的同义词,而不是“文件系统或zip归档文件中的条目”,因此从不提及文件名所有。

这也与Java 9的发展方向相匹配,提供类库是一种自定义的,潜在优化的库格式,而不是一个完整的.class文件的zip容器。

尽管如此,命名包含.class结尾的不同表示的文件将是非常令人沮丧的。

您引用的声明有点奇怪。它始于

给予.class文件相同的名称,它们所包含的公共类仅仅是一绝,...

.class文件没有包含一个public类的。在目前的形式下,它最多只能包含一个类,不一定是public。但它也可能包含一个虚拟类,以提供元信息或从Java 9开始提供模块规范。

另外,为了在默认查找规则中找到,例如,使用URLClassLoader,您不会给.class文件指定所包含类的名称,而是使用其短名称并将其放在从其限定名称的包组件派生的目录结构/路径中。

但第二部分

...但根据JLS这不是严格的。从JLS的角度来看,编译器会选择是否设置这样的限制。

是正确的。如上所述,甚至不需要提供类文件。比较

JLS §1., Introduction

Java编程语言通常被编译设置字节码指令和二进制格式Java虚拟机规范中定义的,Java SE的8版

注字“正常

JVMS §2.1., The class File Format
由Java虚拟机执行

编译代码使用的硬件和操作系统的代表独立的二进制格式,通常(但不一定)存储在一个文件中,称为class文件格式。

“通常(但不一定)” ...

+0

谢谢!关于声明的第一部分,我应该指出“如果他们包含公开课”......不是那个意思。class文件*必须*包含一个公共类,但如果他们这样做的话,他们应该(根据你的回答判断,这只是一种好的编程习惯,但它们应该按照该类的名字命名)。 – Salvioner

+0

关键的一点是,如果您希望像'URLClassLoader'实现的标准查找算法能够工作,则必须遵循命名约定。否则,你将不得不实现你自己的loader(尽管如果命名不同,它不会那么困难)。在Java 9中,不仅有一个新的类加载器实现,而且还有一个特殊的'FileSystem'实现,工具可以用来读取这些模块。 – Holger