2010-07-02 55 views
5

比方說,我的系統使用(靜態)Java應用程序從庫整型常量:本地Java緩存常數

INT =設爲myVal OutsideLibraryClass.CONSTANT_INT;

現在,無需重新編譯我的應用程序,我跑這對一個稍微不同的版本OutsideLibraryClass,其中CONSTANT_INT的價值是不同的。

是我的應用程序將會看到新的值(因爲它撿起來,在運行時)或舊的(因爲該值在我的方法編譯成字節碼)?如果CONSTANT_INT是最終的,它有什麼區別嗎?是否有Java規範的一部分談論這個問題?

+0

參見:http://stackoverflow.com/questions/1693091/public-static-final-variable-in -an-imported-java-class/1693135#1693135 – Dirk 2010-07-02 17:02:39

回答

4

引用常量字段在編譯時,他們表示常數值都解決了。 (JLS 13.1)

+0

呵呵,我從來沒想到會這樣。感謝您的信息! – Pace 2010-07-02 17:10:05

+1

這與Java Puzzlers:Traps,Pitfalls和Corner Cases中的棘手難題93幾乎相同 – Nulldevice 2010-07-02 17:20:52

1

不,它不會拿起新的價值。這是語言規範的一部分。見this question

+0

它取決於CONSTANT_INT的最終修飾符。 – Nulldevice 2010-07-02 17:23:20

+1

@Nulldevice,如果該字段被稱爲常量,那直接意味着最終修飾符IMO。無論如何,什麼樣的圖書館會有非最終的公衆詮釋? – Yishai 2010-07-02 17:29:15

1

從JVM規範:

類變量是使用類聲明中的關鍵字static(§2.9.1)聲明的類類型的字段,或者具有或不具有該關鍵字在靜態接口聲明。類變量是在類或接口被加載時創建的(§2.17.2),並且在創建時初始化爲默認值(§2.5.1)。當它的類或接口被卸載時,類變量有效地停止存在(§2.17.8)。

因此,當ClassLoader加載OutsideLibraryClass時,該值被初始化。當您在myVal上執行賦值語句時,該值將在運行時基於由ClassLoader加載的OutsideLibraryClass類文件加載。因此,如果關閉JVM,交換包含OutsideLibraryClass的jar文件並再次運行它,它將從新類中獲取值。

UPDATE

如果你在談論 實例 的方法中的局部變量的上述聲明是真實的。如果你的myVal變量是在類級別聲明的,那麼說這個變量不會改變的人是正確的。

+0

我確實說過'靜態'。並將其作爲靜態引用。 – DJClayworth 2010-07-02 17:48:27

+0

我應該更仔細地選擇我的話。我指的是'myVal'是方法內的局部變量;我明白你的意思是CONSTANT_INT是最終靜態的。如果你把你的確切的語句,並將其移動到一個類級別的實例變量,你不會拿起新的價值,當你交換罐子。如果您採用相同的語句並將其放在(非靜態)方法中,則在交換jar文件時,您將選取新值。 – proflux 2010-07-02 18:45:51

+0

你試過這個嗎?來自Java Puzzlers的Puzzle 93似乎表示,如果myval是本地變量或實例變量,則該值在編譯時固定。 – DJClayworth 2010-07-02 19:05:45

2

不幸的是你的問題不夠具體回答這個問題,因爲它可能會或可能不會改變,不需要重新編譯。下面是一個例子,其中常數值更改而不重新編譯。

public class Const { 
    public static final int CONSTANT; 
    static { 
     CONSTANT = 4; 
    } 
} 

class Test 
{ 
    int c = Const.CONSTANT; 
} 

這裏還有一個情況下它不會變化而無需重新編譯

public class Const { 
    public static final int CONSTANT = 4; 
} 

class Test 
{ 
    int c = Const.CONSTANT; 
} 
+0

即使這不是我所問的問題,值得+1提醒我們常量必須作爲一個常量由編譯器檢測。 – DJClayworth 2010-07-05 13:25:15