在 Java 中,if(!foo) 和 if(foo == false) 之间的性能差异(如果有)是什么?

2022-09-03 08:31:44

从逻辑上讲,它们是等效的。它们在Java中是如何表示的?编译后,两者之间在字节码或性能方面是否有任何差异?我无法在JLS中找到答案,搜索结果显示了很多关于= vs. == 拼写错误和==/equals()行为的结果。(在这种情况下,符号阻碍了我的搜索;对于未来的搜索者,否定运算符等于false,等于false,而不是条件)。if(!foo)if(foo == false)

为了阻止CW辩论:这个问题不是问人们更喜欢哪种变体或哪种风格更好。我对语言实现的差异很感兴趣,所以有一个正确的答案。相关但不完全是重复的:Java中的 while (x = false) 和 while (!x) 之间的区别?

编辑:

普遍的共识似乎是,一个好的编译器应该将它们优化为同一件事。这是有道理的,也是我所怀疑的,但是 --问一个更学术的问题-- 这种行为是否真的在任何地方被强制要求,或者它“仅仅是”合理的事情?


答案 1

JLS 将指定语句的必需行为。但是,它们的实现方式是编译器和 JVM 的实现细节。

在实践中,任何值得其盐的编译器都应该为这些语句发出相同的字节码。即使没有,JVM也会正确优化它们。

另外,回答这个问题的更好方法是自己检查一下,使用:javap

  1. 编译包含以下内容的 a:Test.java

    class Test {
        void equals(boolean f) {
            if (f == false) {}
        }
        void not(boolean f) {
            if (!f) {}
        }
    }
    $ javac Test.java
    
  2. 解组装它:

    $ 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提供了很多指导)。

只要编译器保持相同的相同行为,编译器就可以自由地实现不同的行为,并有可能具有不同的运行时性能。


答案 2

编译器应在内部解析为相同的代码,因此没有区别。