2011-06-21 109 views
4

我有一個Java項目,涉及類GUIConstants - 各種public static final參數用於佈局圖形用戶界面,因爲不同的組件有時必須是相同的大小或顏色或任何。螞蟻不重新編譯常量

我目前正在做一個可視化重新設計的階段,其中涉及改變這些常數中的一些。然而,ant正在使這一難題。我將更改參數並重新編譯,但仍舊使用舊值。如果我爲其中一個使用它並重新編譯的文件添加一些微不足道的修改,將會使用正確的值。但是它很煩人,而且很容易出錯,不得不查找所有文件並修改它們。當然有一種方法可以強制ant重新編譯未更改的文件......我只是無法在手冊頁中找到它。我的假設是,當編譯一個使用final變量的類時,Java改爲使用該值本身,而不是對該變量指向的任何引用(類似於對常量使用#DEFINE的方式在C中工作)。所以即使變量指向別的東西,原始值也會被烘焙到.class文件中。這是真的? (它不影響我的問題,我只是好奇。)

在此先感謝。

+0

不能相信沒有真正的解決方案。對每個構建使用清理是幾個常量的一個很好的解決方案。 – Stiefel

回答

2

你的假設幾乎是正確的。這不僅僅是final變量,雖然,但所謂的「constant variables」:

我們把一個變量,基本類型或輸入字符串,這是最終的和有一個編譯時間常數表達式(§15.28)常數變量初始化。變量是否爲常量變量可能對類初始化(§12.4.1),二進制兼容性(§13.1,§13.4.9)和明確賦值(§16)有影響。

然後,在上binary compatibility (§13.1)的部分:

引用是恆定變量(§4.12.4)在編譯時被解析爲表示的恆定值的字段。沒有提到這種恆定字段應該是存在於一個二進制文件中的代碼(除類或含有該常量字段,這將有代碼以初始化它接口)

和(§13.4.9)(我的重點):

如果字段是一個常量變量(§4.12.4),則刪除該關鍵字最終或改變其值不會通過使它們不運行中斷與預先存在的二進制兼容性,但除非重新編譯,否則他們將不會看到該字段使用的任何新值。

在之前的工作中,我們利用這種方法建立了一種條件編譯系統,這樣我們就可以生成帶有所有調試語句的生產二進制文件。

當你把這個隨路javac task決定了類重新編譯你得到你所看到的行爲:

沒有相應的.class文件或

只有Java文件在類文件是比老.java文件將被編譯。

注意:Apache Ant僅使用源文件和類文件的名稱來查找需要重建的類。它不會掃描源代碼,因此不會了解有關嵌套類,與源文件名稱不同的類,等等。除了存在/修改時間以外,請參閱<depend>任務以進行依賴性檢查。

解決這一問題將是,每次做一個乾淨的完整的編譯,喜歡的東西ant clean compile最簡單的方法(假設你有一個clean目標,消除所有的類文件)。儘管這可能太慢了。

我也打算建議您看depend任務,正如javac任務的文檔中所建議的那樣,但是查看文檔(我自己並沒有真正使用它),似乎它贏了(請參閱「限制」一節):

這些限制最明顯的例子是,當其他類導出的常量原始數據類型發生更改時,任務無法確定要重新編譯哪些類。

一個可能的解決方法,如果你發現每過慢的時間做一個乾淨的編譯,將是使你的GUIConstants類中的值不會常量,至少你的同時進行更改。您可以通過評論所有final關鍵字來使這些值不是最終的,然後其他類應該會看到您的更改。當你對新值感到滿意時,把final放回原處並重新編譯(並測試當然一切仍然正常)。

+0

final對這個問題沒有影響 –

1

您想要使用clean任務刪除dist目錄中的所有文件。或者你正在放置二進制文件的地方。

2

你的理論是錯誤的。 Java將決賽嵌入到周圍類文件的常量池中,就像它執行任何非決賽一樣。沒有特殊的「最終」優化,只有一個標誌表明它只能在施工過程中設置。

在構建鏈中出現某種錯誤的可能性要好得多,比如從舊源「更新」的類或一組類,或從尚未更新的類「構建」的jar文件,或引用以前版本的jar文件的程序等。驗證這一點的一種快速方法是刪除所有編譯的項目。通常這是通過ant build.xml文件中的「乾淨」目標完成的;然而,這個目標也可能是手寫的,所以不要認爲它總是正確的(特別是如果你增加額外的中間構建步驟,如類增強等)。

0

「理論」似乎都不正確,清除靜態沒有效果,重新編譯清理總是有效,我的構建「系統」幾乎只依賴於子目錄中的源代碼,而沒有其他外部的罐子,所以沒有「陳舊「的課程掛在

在我的情況下,我不得不做一個完整的重建我的來源的一個領域 - 我直接包括一個來源的庫,不需要重新編譯,但包括一個單獨的」 deepclean「的規則,但是與這個問題隔離...

+0

澄清雖然它沒有回答這個問題,但它重要地表明,其他兩個答案也不......爲什麼在這兩個問題上添加完全相同的評論,這將是pedantry。 –

0

DJClayworth在這個answer的答案建議使用類似以下的構造來愚弄編譯器:

public static final int INT_VALUE = Integer.valueOf(100).intValue(); 

它使編譯器看不到此成員的常量字符。我只是測試它,它的工作原理。在將常量改爲上述構造之後,不要忘記執行一次完整的清理。

不是一個美麗的解決方案,但對於暫時的解決方法很有幫助。