2017-10-18 187 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