簡體   English   中英

為什么Java不優化| =賦值?

[英]Why does Java not optimize |= assignments?

對於此示例, t*()始終返回true,其中f*()始終返回false。

假設我們有以下表達式

if ( f1() || t1() || f2() || t2() ){
    // do stuff        
}

如果是這種情況,JVM會優化執行並只執行f1()t1()因為它“理解”無論f2()t2()產生的,都滿足了輸入if語句的要求,因此無需進一步計算。

我正在編寫一個代碼,我寫了這樣的代碼:

boolean b = false;
b |= f1(); // A
b |= t1(); // B
b |= f2(); // C
b |= t2(); // D

我的一位同事看到了這一點,並提到他不確定,但Java可能有可能優化語句C和D,因為從語句B開始b總是true ,這可能會導致一些問題。

我進行了一些測試,好像所有測試都正確執行(這是所需的行為),但我仍然想知道為什么不進行優化? 我認為他可能是正確的,JVM理解一旦b為真,沒有|=操作就會改變它的值。

由於JLS§15.26.2 ,調用沒有得到優化 復合賦值運算符需要評估右側表達式。

如果左側操作數表達式不是數組訪問表達式,則:

  • 首先,評估左側操作數以產生變量。 如果此評估突然完成,則賦值表達式出於同樣的原因突然完成; 不評估右側操作數,也不進行賦值。
  • 否則,保存左側操作數的值,然后評估右側操作數。

  • ...

從歷史上看, 短路條件( &&|| )但不是按位( &| )運算符的傳統至少可以追溯到C(但值得注意的是,在1999年之前C沒有明確的布爾類型) 。

我仍然想知道為什么不進行優化?

因為這會違反JLS。

該聲明

b |= f1();

相當於

b = (boolean)(b | f1());

在上面,JLS 要求 b | f1() b | f1()的評估如下:

  1. 獲取b的值。
  2. 調用f1()並捕獲結果值
  3. 應用| 運算符到兩個值。

該JLS 不允許編譯器跳過調用f1()如果btrue 1。

如果你想要語義(短路),你需要使用b = b || f1(); b = b || f1(); 等等。 (如您所述: b ||= f1()是語法錯誤。)


1 - 實際上,在無法觀察(在單線程程序中) f1()調用已發生或未發生的情況下,理論上允許進行優化。 但是您只能通過仔細檢查JIT編譯器發出的本機代碼來檢測優化。 它只有在呼叫嚴格無副作用時才會發生。

這更多地是關於布爾運算符和位運算符之間的區別。

|=復合運算符是一個按位運算符,意味着將對這兩個項進行求值。

你可以通過設置一個測試來輕松地調試它,其中b被賦值為literal true ,然后是|=賦值給返回boolean值的方法,並且在其中有一個斷點。

斷點將始終觸發。

另一方面,“快捷方式”優化僅適用於布爾運算符: || &&

注意: 這里有關於復合賦值的一些規范,但我找不到|=賦值的相關部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM