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

时间:2016-11-17 20:57:03

标签: java optimization jit

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

通常出于调试目的,我喜欢在调试器中看到这些条件检查的结果,并将它们放在一行中会使事情变得更加困难。如果有六个检查,则代码变得更难以理解。

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

boolean finalResult = result1 && result2 && result3;

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

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

3 个答案:

答案 0 :(得分:2)

你可以这样写:

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

这允许您逐步执行每个条件,并在不执行不必要的代码的情况下查看中间结果。

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

答案 1 :(得分:2)

通常您的代码段不等效。第一个版本必须表现为 as-if 所有函数都被调用,因为你在代码中无条件地调用它们。

代码的第二个版本:

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

不等效,因为&&操作是快捷方式,因此如果任何返回false,则不会调用其余的函数。

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

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

编译器可能无法始终确定某个函数是否具有副作用,或者实际上可能存在只有您知道不重要的副作用(例如,您知道不会发生的ArrayOutOfBoundsException)但编译器无法证明)。因此,编写第二种形式通常会更好,这使得编译器可以使用短路评估,而不管它能够证明哪些功能。

答案 2 :(得分:0)

同意,第二个例子将继续评估,直到它达到错误状态,然后它将返回“false”。短路操作员&&正在使用,因此一旦遇到错误情况,评估就会停止。