0

最近的一个相关问题中,我发现以下代码

public static void main(String[] args) {
/*1*/        int x;
/*2*/        boolean found = false;
/*3*/        if (!found)
/*4*/            x = -1;

/*5*/        System.out.println(x);
    }

有编译器错误 x 不是 init.(initialized)。我很惊讶编译器无法推理 init。特别是因为此代码似乎不需要任何运行时推理,如下所示:

  1. 在指示的第 2 行,found设置false
  2. 第 2 行和第 3 行之间没有代码。
  3. 所以到达第 3 行!found是必然的,true所以 init 是不可避免的。

我想知道这是否正确。我依稀记得编译器优化可以改变语句的执行顺序。这在这里起作用吗?是否有可能在第 3 行和第 4 行之前到达第 5 行?


环境。
openjdk 15.0.2 2021-01-19
OpenJDK Runtime Environment (build 15.0.2+7-27)
OpenJDK 64-Bit Server VM (build 15.0.2+7-27, mixed mode, sharing)
javac 15.0.2 Windows 10

4

1 回答 1

1

请参阅我对另一个问题的(迟到的)答案。规范要求进行源代码分析。

这不是按照您建议的方式重新排序代码的情况;这会改变行为,这是被禁止的。

考虑一般情况:如果在计算完成之前允许使用计算,那么没有什么是可预测的。

但是,在您的示例中,允许使用足够智能的编译器将生成的代码优化为(有效)System.out.println(-1)。这两个变量实际上都不是必需的。

如果发生这样的事情,它不会影响确定分配所需的检查。从逻辑上讲,简化是在验证源代码之后发生的。

您必须检查生成的字节码以查看实际发生的情况。此外,在 Java 中,可以通过即时编译为本机代码来“稍后”完成优化。

于 2021-06-12T15:47:47.773 回答