我阅读了 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) 确实保证:
Each argument expression appears to be fully evaluated before any part of any argument expression to its right.
还有 15.12.4.2:
Evaluation then continues, using the argument values, as described below.
“出现”部分允许进行一些优化,但不能可见。所有参数都在之前“评估然后继续”评估的事实表明,在方法执行之前,参数确实已完全评估。 (或者至少,这是可见的结果。)
例如,如果您有以下代码:
int x = 10;
foo(x + 5, x + 20);
可能对其进行优化以并行评估 x + 5
和 x + 20
:您无法检测到这发生了。
但在您给出的情况下,您将能够检测到在调用 obj.myBoolean( )
,因此根本不会成为有效的优化。
简而言之:您可以假设一切都将以此处显而易见的方式执行。
关于java - 在这种方法调用和传入参数的情况下,是否保证 Java 评估顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18181170/