逻辑上,if(!foo)
和if(foo == false)
是等效的。它们如何用Java表示?编译后两者在字节码或性能方面有什么区别吗?我无法在JLS中找到答案,搜索提出了很多关于= vs. ==拼写错误和== / equals()行为的结果。 (在这种情况下,符号妨碍了我的搜索;对于未来的搜索者,否定操作符,等于错误,等于错误,而不是条件)。
要阻止CW辩论:这个问题不是要求人们选择哪种变体,哪种变体被认为是更好的风格。我对语言实现的差异感兴趣,所以有一个正确的答案。相关但不是很重要:Difference between while (x = false) and while (!x) in Java?
编辑:
普遍的共识似乎是一个好的编译器应该优化它们到同一个东西。这是有道理的,也是我所怀疑的,但是 - 提出更多的学术问题 - 这种行为实际上是在任何地方强制执行,还是“只是”合理的事情呢?
答案 0 :(得分:44)
JLS将指定语句所需的行为。但是,它们的实现方式是编译器和JVM的实现细节。
实际上,任何有价值的编译器都应为这些语句发出相同的字节码。即使不是,JVM也会对它们进行适当的优化。
此外,更好的方法是使用javap
:
使用以下内容编译Test.java
:
class Test {
void equals(boolean f) {
if (f == false) {}
}
void not(boolean f) {
if (!f) {}
}
}
$ javac Test.java
解组:
$ javap -c Test
Compiled from "Test.java"
class Test extends java.lang.Object{
Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
void equals(boolean);
Code:
0: iload_1
1: ifne 4
4: return
void not(boolean);
Code:
0: iload_1
1: ifne 4
4: return
}
更新: 回答你关于“学术”问题的问题。如上所述,JLS只关注行为。标准中没有任何内容实际指定它应该如何实现(嗯,JVMS提供了很多指导)。
只要编译器保留相同的相同行为,编译器就可以自由地实现它,可能会有不同的运行时性能。
答案 1 :(得分:12)
编译器应该在内部解析相同的代码,因此没有区别。
答案 2 :(得分:0)
尝试decompiling the byte code,看看代码看起来有多么不同。我猜测编译将几乎完全相同地解决它们,任何微小的差异都会导致可忽略的性能差异。
答案 3 :(得分:0)
好的,一个更完整的答案:
如果任何编译器为这些变体生成不同的字节码,我会感到非常惊讶。对于任何感兴趣的人来说,使用反汇编程序检查它应该很容易。
鉴于两个表达式(最有可能)编译为相同的字节码,我预计在大小或性能方面没有差异。
答案 4 :(得分:0)
JLS说
表达式 评估一个if块,然后是 该表达式的结果与之比较 真
在非案例和比较对象案例中,需要评估表达式,然后将其与true进行比较。如果您正在检查某个值而不是对其执行操作,那么表达式评估将变为无操作时,可能会产生理论上的性能优势。
但在这种情况下,我希望JIT为两个表达式生成相同的字节码。
答案 5 :(得分:0)
为这两个结果生成的字节码应该没有区别,除非你为资源非常有限的设备创建代码(在这种情况下你不应该用Java编写),否则差别可以忽略不计你应该决定编写这段代码的两种方法中哪一种是更明显的解决方案。
答案 6 :(得分:0)
对微观优化的思考几乎在任何情况下浪费时间并导致以错误的方式思考......
答案 7 :(得分:0)
我问了一个关于C ++ / VS2008的类似问题。
Would VS2008 c++ compiler optimize the following if statement?
为了避免在C ++中使用= vs ==拼写错误,你会倾向于写
if (NULL == ptr) { ... }
if (false == boo) { ... }
if (20 == num) { ... }
等
在你习惯它之前,这个可读性稍差。