3 回答

TA貢獻1802條經驗 獲得超4個贊
我從未將編譯時間視為 Java 中的設計考慮因素(從 v 1 開始使用 Java)。具體到您的問題,語言規范在這方面沒有提供任何保證。它可能會因版本和實現而異。
在 javac 之外,構建系統可能會做明智的事情,例如參見:https : //blog.gradle.org/incremental-compiler-avoidance
編輯:只需仔細檢查,即使沒有更改,也要javac重新編譯源:
$ java -version
openjdk version "10.0.2" 2018-07-17
$ javac *.java && ls -l A.*
-rw-rw-r-- 1 usr usr 143 Oct 14 20:07 A.class
-rw-rw-r-- 1 usr usr 59 Oct 14 19:57 A.java
等了一分鐘后...
$ javac *.java && ls -l A.*
-rw-rw-r-- 1 usr usr 143 Oct 14 20:08 A.class
-rw-rw-r-- 1 usr usr 59 Oct 14 19:57 A.java

TA貢獻1827條經驗 獲得超9個贊
不,沒有顯著差異。大部分編譯時間都在解析,這完全不受此影響。
重點是:給定文件'MySource.java',包含某種類型的MySource,如果MySource 的任何父類型被重新定義,你真的應該重新編譯這個類。你不必,java會盡力而為,但現在你可以創造瘋狂的場景(例如,如果你更新父類型來添加一個新的抽象方法,就像一個必須實現的方法,現在你仍然有一個沒有的子類型。當您嘗試混合由不同的編譯運行生成的這些類時,會拋出運行時錯誤)。
使用接口的重點是避免它:即使具體實現確實發生了變化,也有一個根本沒有改變的超類型(沒有人接觸過接口定義)。
你會認為這意味著:嘿,太好了,現在我什至不必重新編譯這個文件。但這并不重要。與 C 語言相比,java 編譯時間非??欤ㄖ恍鑾酌腌娂纯赏瓿纱罅宽椖浚?,而且很難有一個足夠智能的構建系統來意識到在這種情況下不需要重新編譯。不; 關鍵是有點自我控制:如果你有一個拆分項目,其中接口/父類在源代碼庫 A 中,而子類在 B 中,事情就會中斷:除非 A 和 B 由相同的人維護人和重建同時,你有問題。
因此,重點是:您擁有“公共 API”,例如,除非您有充分的理由,否則不得更改您規定的類型。使接口更明確哪些位不會改變。這使源代碼庫 A 的作者可以自由更改(非公共/導出)實現類,只要他們不弄亂接口,而不必去調用源代碼庫 B 的優秀人員并告訴他們: 呃,抱歉,我們改變了一些東西,你必須做一個完整的重建。

TA貢獻1785條經驗 獲得超4個贊
如果更改具體類,則只需要重新編譯具體類及其調用者。如果您有一個接口,并且人們正在調用接口而不是具體類,那么他們不會被視為具體類的調用者,也不需要重新編譯。這是接口幫助減少編譯時間的唯一方法,AFAICT。
每個對接口進行類型優化的 Java 實現都將該優化推遲到運行時 (HotSpot) 優化器:有關更多信息,您正在尋找的術語是“專業化”。Java 編譯器本身(即:Java => 字節碼編譯器)實際上幾乎沒有進行優化,并且由于無法在運行時對代碼進行推理(參見:Haskell 的編譯器)而受到阻礙。這是因為您可以進行動態代碼加載:可以在運行時通過類路徑修改和反射來更改接口的可能實現集。
添加回答
舉報