Java編譯時常量和運行時常量 編譯期常量指的就是程式在編譯時就能確定這個常量的具體值。 非編譯期常量就是程式在運行時才能確定常量的值,因此也稱為運行時常量。 在Java中,編譯期常量指的是用final關鍵字修飾的基本類型或String類型並直接賦值(非複雜運算)的變數(無論是否用static修飾) ...
Java編譯時常量和運行時常量
編譯期常量指的就是程式在編譯時就能確定這個常量的具體值。
非編譯期常量就是程式在運行時才能確定常量的值,因此也稱為運行時常量。
在Java中,編譯期常量指的是用final關鍵字修飾的基本類型或String類型並直接賦值(非複雜運算)的變數(無論是否用static修飾),是編譯器的一種優化,體現在位元組碼文件中;運行是常量是由運行時解釋器解釋完成的。
運行時常量很容易理解,接下來會簡單的結合位元組碼文件來介紹編譯時常量及使用風險。
public class ConstantTest { public final int a = 1; //編譯時常量 public final int b = 1+2; //編譯時常量 支持加減乘除等簡單運算 public final int c = b+3; //編譯時常量 public final static int d = 10; //編譯時常量 public final String str1 = "abc"; //編譯時常量 public final String str2 = "def" + "ghi"; //編譯時常量 支持字元串的連接 public final String str3 = str2 + "jkl"; //編譯時常量 public final static String str4 = "static str"; //編譯時常量 public final double e = Math.random(); //運行時常量 public final ConstantTest test = new ConstantTest(); //運行時常量 }
下麵是編譯後相應的位元組碼信息:
註意!!!!!!
類B中所有引用類A中用static final修飾的靜態編譯時常量都會在編譯時全部替換為相應的數值或字元串,所以當修改了類A中的靜態編譯時常量時,類A和類B都要重新編譯,如果只重新編譯類A,則類B還是會引用之前的常量。
以下是案例:
類ConstantTest:
public class ConstantTest { public final int a = 1; public final int b = 1+2; public final int c = b+3; public final static int d = 10; public final String str1 = "abc"; public final String str2 = "def" + "ghi"; public final String str3 = str2 + "jkl"; public final static String str4 = "static str"; public final double e = Math.random(); public final ConstantTest test = new ConstantTest(); }
類Test引用ConstantTest中的靜態編譯時常量:
public class Test{ public int m = ConstantTest.d; public static int n = ConstantTest.d; public final int g = ConstantTest.d; public static final int j = ConstantTest.d; public static void main(String[] args) { int k = ConstantTest.d; System.out.println("m="+new Test().m); System.out.println("n="+n); System.out.println("g="+new Test().g); System.out.println("j="+j); System.out.println("k="+k); } }
首先全部編譯,運行Test類:
修改ConstantTest中靜態常量的值為20後只重新編譯ConstantTest,運行結果:
重新編譯Test後,運行結果:
最後總結一下:
- 編譯期常量指的是用final關鍵字修飾的基本類型或String類型並直接賦值(非複雜運算)的變數(無論是否用static修飾);
- 運行時常量是程式在運行時才能確定值的一種常量;
- 所有引用其他類中靜態編譯時常量(一般就叫靜態常量,用static final修飾)的類在位元組碼中全部替換為相應常量的值,所以引用靜態常量並不會觸發該類的的初始化。