[英]Is Java evaluation order guaranteed in this case of method call and arguments passed in
我在JLS 15.7.4和15.12.4.2上做了一些閱讀,但它並不能保證不會有任何編譯器/運行時優化會改變評估方法參數的順序。
假設以下代碼:
public static void main (String[] args) {
MyObject obj = new MyObject();
methodRelyingOnEvalOrder(obj, obj.myMethod());
}
public static Object methodRelyingOnEvalOrder(MyObject obj, Object input) {
if (obj.myBoolean())
return null;
else
return input;
}
是否保證編譯器或運行時不會進行錯誤優化,如下所示? 這種優化可能看起來是正確的,但是當評估順序很重要時,這是錯誤的。
在呼叫的情況下obj.myMethod
改變將由返回的值obj.myBoolean
,這是至關重要的obj.myMethod
首先被稱為methodRelyingOnEvalOrder
需要這種改變首先發生。
//*******************************
//Unwanted optimization possible:
//*******************************
public static void main (String[] args) {
MyObject obj = new MyObject();
methodRelyingOnEvalOrder(obj);
}
public static Object methodRelyingOnEvalOrder(MyObject obj) {
if (obj.myBoolean())
return null;
else
return obj.myMethod();
}
//*******************************
如果可能,請顯示支持您的答案的一些來源或Java文檔。
注意:請不要要求重寫代碼。 這是一個特殊情況,我在質疑評估順序保證和編譯器/運行時優化保證。 obj.myMethod
的執行必須在main
方法中執行。
您提到的JLS(15.7.4) 確實保證:
每個參數表達式似乎在其右邊的任何參數表達式的任何部分之前被完全計算。
以及15.12.4.2:
然后使用參數值繼續評估,如下所述。
“似乎”部分允許進行一些優化,但它必須不可見 。 在 “評估然后繼續” 之前評估所有參數的事實表明,在方法執行之前,參數確實已經完全評估。 (或者至少,這是可見的結果。)
例如,如果你有以下代碼:
int x = 10;
foo(x + 5, x + 20);
有可能優化它以並行地評估x + 5
和x + 20
:你無法檢測到這種情況。
但是在你給出的情況下,你將能夠在調用obj.myBoolean()
之后檢測到對obj.myMethod
的調用,因此根本不是有效的優化。
簡而言之:你可以假設一切都會以明顯的方式執行。
除了參數評估順序之外,在調用方法時執行的步驟概述及其順序 ,在第15.12.4節中進行了解釋。 方法調用的運行時評估,清楚地表明在執行方法代碼之前執行所有參數評估。 引用:
在運行時,方法調用需要五個步驟。 首先,可以計算目標參考。 其次,評估參數表達式 。 第三,檢查要調用的方法的可訪問性。 第四,找到要執行的方法的實際代碼。 第五,創建新的激活幀,如果需要則執行同步,並且將控制轉移到方法代碼 。
您提出的僅在控制轉移到方法代碼后才評估參數的情況是不可能的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.