java - 在这种方法调用和传入参数的情况下,是否保证 Java 评估顺序

标签 java runtime compiler-optimization execution operator-precedence

我阅读了 JLS 15.7.415.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 + 5x + 20:您无法检测到这发生了。

但在您给出的情况下,您能够检测到在调用 obj.myBoolean( ),因此根本不会成为有效的优化。

简而言之:您可以假设一切都将以此处显而易见的方式执行。

关于java - 在这种方法调用和传入参数的情况下,是否保证 Java 评估顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18181170/

相关文章:

java - 保存后 hibernate 插入

java - SharedPreferences 如何与 UpdateUI 配合?

android - 如何使管道符号或 Grep 在 Android 进程运行时命令中工作?

c# - 根据 c# 中的用户输入在运行时动态附加字段

c++ - 虚拟表查找的优化

java - 验证 Swing GUI 中的所有字段

java - 使用 JEditorPane 打开文本文件

delphi - 如何在运行时创建摘要页脚?

循环中的 C++ 浮点错误与单个表达式中的错误

gcc - "compiler option"-auxbase-strip 有什么作用?