這道題目揭示 Java 編譯期常量折疊優化導致的「修改常量值不重新編譯調用方,運行時仍讀取舊值」的經典行為。
// Ques1116.java
public class Ques1116 {
public static void main(String[] args) {
System.out.println("常量是" + Const.NUM);
}
}
// Const.java
public class Const {
public final static int NUM = 110;
}
javac Ques1116.java Const.java → java Ques1116 輸出 110Const.NUM = 120javac Const.javajava Ques1116final static 基本類型/字符串屬於 編譯期常量 (JLS 15.28)Ques1116 時,將 Const.NUM 的值 內聯 到字節碼常量池:ldc 110Ques1116 類文件 不再依賴 Const 類,甚至刪除 Const.class 也能運行Const 只更新 Const.class 常量池,Ques1116.class 仍持有舊值 110javap -c Ques1116.class
# 輸出包含:ldc #2 // int 110
# 無 CONSTANT_Class_info 指向 Const
clean compile 自動處理)final static 基本類型,改用:
public static final String CONFIG = "..."; (非基本類型/非字符串字面量)若 NUM 為 Integer 或自定義對象,編譯器不會折疊,運行時會動態讀取最新值。這也是為何 String 常量折疊行為與包裝類型不同的原因。