常數表示式

常量表示式是一個表示式,它產生一個基本型別或一個 String,並且其值可以在編譯時計算為文字。表示式必須在不丟擲異常的情況下進行求值,並且必須僅由以下內容組成:

  • 原始和字串文字。

  • 型別轉換為基本型別或 String

  • 以下一元運算子:+-~!

  • 以下二元運算子:*/%+-<<>>>>><<=>>===!=&^|&&||

  • 三元條件運算元 ? :

  • 帶括號的常量表示式。

  • 引用常量變數的簡單名稱。 (常量變數是宣告為 final 的變數,其中初始化表示式本身是一個常量表示式。)

  • <TypeName> . <Identifier> 形式的合格名稱,用於引用常量變數。

請注意,上面的列表不包括 ++--,賦值運算子,classinstanceof,方法呼叫以及對常規變數或欄位的引用。

String 型別的常量表示式導致 interned``String,並且使用 FP-strict 語義評估常量表示式中的浮點運算。

用於常量表示式

可以在任何可以使用普通表示式的地方使用常量表示式(幾乎)。但是,它們在以下情況下具有特殊意義。

switch 語句中的 case 標籤需要常量表示式。例如:

switch (someValue) {
case 1 + 1:            // OK
case Math.min(2, 3):   // Error - not a constant expression
    doSomething();
}

當賦值右側的表示式是常量表示式時,賦值可以執行原始縮小轉換。只要常量表示式的值在左側型別的範圍內,就允許這樣做。 (參見 JLS 5.1.35.2 )例如:

byte b1 = 1 + 1;             // OK - primitive narrowing conversion.
byte b2 = 127 + 1;           // Error - out of range
byte b3 = b1 + 1;            // Error - not a constant expession
byte b4 = (byte) (b1 + 1);   // OK

當常量表示式用作 dowhilefor 中的條件時,它會影響可讀性分析。例如:

while (false) {
    doSomething();           // Error - statenent not reachable
}
boolean flag = false;
while (flag) {
    doSomething();           // OK
}

(請注意,這不適用於 if 語句 .Java 編譯器允許 if 語句的 thenelse 塊無法訪問。這是 C 和 C++中條件編譯的 Java 模擬。)

最後,一個類或具有常量表示式初始化器的介面中的 static final 欄位被急切初始化。因此,即使在類初始化依賴圖中存在迴圈,也可以保證在初始化狀態下觀察這些常量。

有關更多資訊,請參閱 JLS 15.28。常數表示式