Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java是否在运行时优化函数调用以进行不必要的布尔比较?_Java_Optimization_Jit - Fatal编程技术网

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

Java是否在运行时优化函数调用以进行不必要的布尔比较?,java,optimization,jit,Java,Optimization,Jit,如果其中一个函数不返回true,java会在运行时调用这三个函数吗 通常出于调试目的,我喜欢在调试器中看到这些条件检查的结果,而将它们放在一行中会使这变得更加困难。如果有半打检查,那么代码就会变得更不可读 boolean result1 = CheckSomething(); boolean result2 = CheckSomethingElse(); boolean result3 = CheckSomeOtherThing(); boolean finalResult = result1

如果其中一个函数不返回true,java会在运行时调用这三个函数吗

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

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

boolean finalResult = result1 && result2 && result3;
如果Java在运行时没有优化这个条件,那么应该通过编写这样的代码来实现更好的性能,代价是无法在调试器中轻松查看中间值

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

同意,第二个示例将继续求值,直到达到false条件,然后返回“false”。正在使用短路运算符&,因此一旦遇到错误情况,评估将停止

您可以这样写:

boolean result1 = condition1();
boolean result2 = result1 && condition2();
boolean result3 = result2 && condition3();
这允许您逐步检查每个条件,并查看中间结果,而无需执行不必要的代码

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

的第一个结果。通常,您的代码片段并不等效。第一个版本的行为必须像调用所有函数一样,因为您在代码中无条件地调用它们

代码的第二个版本:

boolean finalResult = CheckSomething() && CheckSomethingElse() && CheckSomeOtherThing();
不是等效的,因为
&&
操作是快捷方式,因此如果任何函数返回false,则不会调用其余函数

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

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


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

在上一个示例中,if
CheckSomething()
返回false其他函数将不会被调用@matiaselgart的可能重复项这将是另一种问题。他问的是编译器是否会生成不同的字节码,而不是在布尔运算的结果已知(事实并非如此)后是否继续求值。如果这些函数中的任何一个有副作用,Java需要在您的第一个代码段中执行副作用。@Stefan-我认为他所说的不仅仅是不同的字节码,因为他标记了它
jit
。字节码肯定是不同的,但编译后的代码肯定不是。或者仅仅是一个
result
变量。@Andreas这个问题的主要原因是能够看到中间结果。只有一个变量就可以完全防止这种情况发生。不是真的。您可以在逐步完成代码时看到中间结果。一般来说,一旦越过变量范围的末尾,就无法看到它是什么。这也不例外。一旦跨过下一行,上一行的结果将不再可用。当然,单独的变量会扩展中间值的范围,但重用单个变量并不会阻止您看到它们。我刚刚意识到您可能误解了我的第一条评论。我不是想把这3条语句合并成一条语句,我只是想用一个变量而不是三个变量,即
boolean result=condition1();结果=结果和条件2();结果=结果和条件3()使用单独的变量允许我只有一个断点,当我停在那里时,我可以查看所有三个值,并查看哪个条件是第一个返回
false
。使用单个变量是不可能的。如果这三种方法都没有副作用,编译器甚至可以对它们重新排序,首先进行更便宜的检查。或者首先执行最有可能返回
false
的检查(跳过其他检查的可能性最大)。由于这在使用短路变体时甚至是正确的,因此建议始终使用短路形式仍然是正确的。