1 + 2
是一個常量表達式,而a + b
不是。
它對評估它們很重要。
第一個將在編譯時完成,第二個在運行時完成。
的JLS 8狀態:
15.28。常量表達式
常量表達式是一個表達式表示原始 類型或字符串的一個值,該值不會突然完成並僅使用 由下列:
原始類型和文字的
........................
這裏:
short c = 1 + 2;
1 + 2
是由兩個int
文字和一個加法運算符組成。
所以它被認爲是一個常數表達式。
在編譯時評估常量表達式。
所以short c
作爲3
這裏評估是一個示例類:
package stackoverflow;
public class EvaluationClass {
public void foo(){
short c = 1 + 2;
}
}
下面是反彙編代碼:
Compiled from "EvaluationClass.java"
public class stackoverflow.EvaluationClass {
public stackoverflow.EvaluationClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()
4: return
public void foo();
Code:
0: iconst_3
1: istore_1
2: return
}
我們可以看到,裝載3
int
到0: iconst_3
指令堆棧。
鑑於此:
short a = 1;
short b = 2;
short c = a + b;
a + b
僅在運行時評價爲a
和b
不是恆定值。
它們的值可能在任何時候都會改變。
請注意,如果a
和b
有效變異,則編譯器不會試圖通過閱讀每個語句來猜測。
它認爲它只能在運行時評估a + b
。
現在在這種情況下,爲什麼a + b
不會產生short
而是int
?
由於JLS 8規定:
4.2.2。整數運算
如果比的變速操作者以外的整數操作者有long類型中的至少一個 操作數,則該操作被執行使用64位 精度,數值運算符的結果是類型長的。 如果另一個操作數不長,則首先擴展(§5.1.5),以便通過數字提升鍵入 (§5.6)。
否則,操作是使用32位精度進行的,並且 數值運算符的結果是int類型的結果。如果任一操作數 不是int,則首先將其擴展爲通過數字提升來鍵入int。
作爲一個側面說明,如果更改代碼,使a
和b
constants
:
final short a = 1;
final short b = 2;
short c = a + b;
這將現編譯罰款a + b
將作爲一個常量表達式進行評估(3
) 。
由於兩個操作數都是編譯時間常數,因此可以在編譯時計算「1 + 2」。換言之,'short c = 1 + 2;'將編譯爲'short c = 3;'。如果結果超出「短」範圍,您仍然會出錯。 – Pshemo
@Pshemo那麼這意味着一個'int'會被明確地降低爲'short'?因爲1 + 2或者被解析爲'short'仍然會被評估爲'int',否? – dosdebug
@dosdebug不,這裏沒有添加。它的編譯方式與'short c = 3'相同;' – Neo