2012-01-17 65 views
4

假設您編譯了以下兩個類。第一個意思是代表客戶;第二個是圖書館課。運行時不反映的常量值

public class Test{ 
    public static void main(String[] args) { 
     System.out.println(Lib.FIRST + " " + 
          Lib.SECOND + " " + 
          Lib.THIRD); 
    } 
} 


public class Lib{ 
    private Lib() { }; // Uninstantiable 
    public static final String FIRST = "the"; 
    public static final String SECOND = null; 
    public static final String THIRD = "set"; 
} 

打印:

{空集}

現在假設你修改庫類,如下所示,並重新編譯,但沒有客戶端程序:

public class Lib{ 
    private Lib() { }; // Uninstantiable 
    public static final String FIRST = "physics"; 
    public static final String SECOND = "chemistry"; 
    public static final String THIRD = "biology"; 
} 

打印:

{化學組}

爲什麼SECOND值改變,但不是FIRSTTHIRD

+0

有沒有在classpath中兩個 「庫」 類?你重新啓動了VM嗎?你的容器是什麼? – JustinKSU 2012-01-17 21:19:48

+2

這是直接[Java Puzzlers](http://www.amazon.com/Java-Puzzlers-Traps-Pitfalls-Corner/dp/032133678X)。相同的字符串常量和一切。如果你想了解Java的更好的例子,這是一個很棒的閱讀。 – yshavit 2012-01-17 21:19:56

+1

這個問題確實是來自Java Puzzlers(拼圖#93)的逐字剽竊。 – 2012-01-20 00:56:53

回答

7

這是一個已知的警告 - 當你編譯你的客戶端程序時,常量是內聯的,所以你必須重新編譯它。

參見:

+1

(+1)好奇......不知道。 – NPE 2012-01-17 21:20:15

+0

這是可以接受的答案,但答案並不十分微妙。具體來說,null不是一個常量表達式,所以它不是內聯的,而其他兩個值是用一個常量表達式定義的,所以它們的值是內聯的(這就是爲什麼「化學集」是最終被打印的原因)。 – 2012-01-20 01:07:11

3

這些值(即「the」和「set」)是內聯的,而編譯時編譯器不會內聯null。爲了避免這種情況,你可以使用一個訪問器方法。

+0

在靜態字段上使用訪問方法時不鼓勵使用嗎?這是一個特例嗎? – kosa 2012-01-17 21:23:02

+0

我只是說如果他想避免重新編譯客戶端類本身。 – 2012-01-17 21:24:15

+0

不,我完全理解你的意圖,我不是說你說錯了什麼,不要誤會我的意思。只是試圖看看你是否知道有任何使用accessor的例外。 – kosa 2012-01-17 21:28:01