Java中的布尔表达式优化

fjs*_*jsj 3 java compiler-construction optimization boolean-logic boolean-expression

考虑Java中的以下方法:

public static boolean expensiveComputation() {
    for (int i = 0; i < Integer.MAX_VALUE; ++i);
    return false;
}
Run Code Online (Sandbox Code Playgroud)

以下主要方法:

public static void main(String[] args) {
    boolean b = false;
    if (expensiveComputation() && b) {
    }
}
Run Code Online (Sandbox Code Playgroud)

逻辑连接(与&&相同)是可交换操作.那么为什么编译器不会将if语句代码优化为等效代码:

if (b && expensiveComputation()) {
}
Run Code Online (Sandbox Code Playgroud)

哪个有使用短路评估好处

此外,编译器是否尝试对布尔值进行其他逻辑简化或置换以生成更快的代码?如果没有,为什么?当然,一些优化会非常困难,但我的例子并不简单?调用方法应该总是比读取布尔值慢,对吧?

先感谢您.

Sea*_*ean 17

它不会这样做,因为expensiveComputation()可能有副作用,改变程序的状态.这意味着评估布尔语句中表达式的顺序(expensiveComputation()和b)很重要.您不希望编译器将错误优化到编译的程序中,对吗?

例如,如果代码是这样的话

public static boolean expensiveComputation() {
        for (int i = 0; i < Integer.MAX_VALUE; ++i);
        b = false;
        return false;
}

public static boolean b = true;
public static void main(String[] args) {
        if (expensiveComputation() || b) {
        // do stuff
        }
}
Run Code Online (Sandbox Code Playgroud)

在这里,如果编译器执行了你的优化,那么//do stuff当你不期望它通过查看代码时会运行(因为b,它最初是真的,首先被评估).

  • 它与`||`并没有什么不同.可以进行相同类型的优化,它具有相同的含义.这只是我想到的第一个具有直接显着效果的例子,这与他的例子有关. (5认同)

Bar*_*lly 8

因为expensiveComputation()可能有副作用.

由于Java并不旨在成为一种功能纯粹的语言,因此它不会禁止程序员编写具有副作用的方法.因此,编译器分析功能纯度可能没有太多价值.然后,像你这样的优化在实践中不太可能是非常有价值的,因为expensiveComputation()通常需要执行,以获得副作用.

当然,对于程序员来说,b如果他们期望它是假的并且明确地希望避免昂贵的计算,那么很容易放第一个.