Java是否在运行时为不必要的布尔比较优化函数调用



如果其中一个不返回true, java实际上会在运行时调用所有三个函数吗?

通常出于调试目的,我喜欢在调试器中看到这些条件检查的结果,将它们放在一行会使调试变得更加困难。如果有六次检查,那么代码将变得更加不可读。

boolean result1 = CheckSomething();
boolean result2 = CheckSomethingElse();
boolean result3 = CheckSomeOtherThing();
boolean finalResult = result1 && result2 && result3;

如果Java在运行时没有优化这个条件,那么应该通过这样编写代码来获得更好的性能,但代价是无法在调试器中轻松看到中间值。

boolean finalResult = CheckSomething() && CheckSomethingElse() && CheckSomeOtherThing();

一般来说你的代码片段是不相等的。第一个版本的必须表现得好像所有函数都被调用了,因为你在代码中无条件地调用了它们。

第二个版本的代码:

boolean finalResult = CheckSomething() && CheckSomethingElse() && CheckSomeOtherThing();

不等价,因为&&操作是快捷方式,所以如果任何函数返回false,则不会调用其他函数。

在解释器中运行时,您可以期望第一个版本的代码实际调用所有方法。

现在,有趣的部分:在编译代码之后,编译器现在能够"查看"各种函数,确定它们是纯函数,没有副作用,并且它可以将两个版本编译为相同的。事实上,如果函数非常简单,最好将两个版本的编译为总是调用所有三个函数,因为如果任何结果是不可预测的,合并三个布尔结果并检查一次可能会更快。

编译器可能并不总是能够确定一个函数是否有副作用,或者实际上可能有副作用,只有你知道不重要(例如,一个ArrayOutOfBoundsException,你知道不会发生,但编译器不能证明)。因此,通常最好编写第二种形式,这种形式允许编译器使用短路求值,而不管它能够证明关于函数的什么。

你可以这样写:

boolean result1 = condition1();
boolean result2 = result1 && condition2();
boolean result3 = result2 && condition3();

这允许您逐步执行每个条件,并查看中间结果,而无需执行不必要的代码。

您还可以在result3行之后设置一个断点,这将显示返回false的第一个结果。

同意,第二个例子将继续求值,直到达到false条件,然后它将返回"false"。短路操作员&&因此,一旦遇到假条件,求值就会停止。

最新更新