t*()對于此示例,始終返回 true,而f*()始終返回 false。假設我們有以下表達式if ( f1() || t1() || f2() || t2() ){ // do stuff }如果是這種情況,JVM 會優化執行并僅執行,f1()并且t1()因為它“理解”無論什么f2()和t2()yield,都滿足了輸入 if 語句的要求,因此不需要進一步的計算。我正在編寫這樣的代碼:boolean b = false;b |= f1(); // Ab |= t1(); // Bb |= f2(); // Cb |= t2(); // D我的一位同事看到了這一點,并提到他不確定,但 Java 有可能優化語句 C 和 D,因為b總是true從語句B開始,這可能會導致一些問題。我進行了一些測試,似乎所有測試都被正確執行(這是所需的行為),但我仍然想知道為什么這沒有得到優化?我想他可能是對的,JVM 知道一旦b為真|=,對它的任何操作都不會改變它的值。
3 回答

慕雪6442864
TA貢獻1812條經驗 獲得超5個贊
由于JLS §15.26.2,調用不會被優化掉。復合賦值運算符需要計算右側的表達式。
如果左操作數表達式不是數組訪問表達式,則:
首先,評估左邊的操作數以產生一個變量。如果這個評估突然完成,那么賦值表達式也會因為同樣的原因突然完成;不計算右側操作數,也不進行賦值。
否則,保存左側操作數的值,然后評估右側操作數。
...
從歷史上看,短路條件 ( &&
, ||
) 而不是按位 ( &
, |
) 運算符的傳統至少可以追溯到 C(但可能值得注意的是,C 直到 1999 年才具有明確的布爾類型)。

撒科打諢
TA貢獻1934條經驗 獲得超2個贊
我仍然想知道為什么這沒有得到優化?
因為那將違反 JLS。
該聲明
b |= f1();
相當于
b = (boolean)(b | f1());
另外,在上述中,JLS要求即b | f1()
如下評價:
獲取 的值
b
。調用
f1()
并捕獲結果值將
|
運算符應用于兩個值。
該JLS不會讓編譯器跳過通話f1()
,如果b
是true
1。
如果你想要那個語義(短路),你需要使用b = b || f1();
等等。(正如您所指出的:b ||= f1()
是語法錯誤。)
1 - 實際上,在無法(在單線程程序中)觀察到f1()
調用發生或未發生的情況下,理論上可以允許優化。但是,您只能通過仔細檢查JIT 編譯器發出的本機代碼來檢測優化。只有在調用完全沒有副作用的情況下才會發生這種情況。
添加回答
舉報
0/150
提交
取消