15

Logically, if(!foo) and if(foo == false) are equivalent. How are they represented in Java? Is there any difference between the two after compilation, either in the bytecode or in performance? I was unable to find an answer in the JLS, and searching brought up a lot of results about = vs. == typos and ==/equals() behavior. (In this case, the symbols hampered my searching; for future searchers, negation operator, equals false, equal to false, not condition).

To head off the CW debate: this question is NOT asking which variant people prefer or which is considered better style. I am interested in the differences in the implementation of the language, so there is a correct answer. Related-but-not-quite-a-dupe: Difference between while (x = false) and while (!x) in Java?

EDIT:

The general consensus seems to be that a good compiler should optimize these to the same thing. That makes sense and is what I suspected, but -- to ask an even MORE academic question -- is that behavior actually mandated anywhere, or is it "merely" the reasonable thing to do?

Community
  • 1
  • 1
Pops
  • 30,199
  • 37
  • 136
  • 151
  • Keep in mind this is compiler-specific. – danben Jan 11 '10 at 17:09
  • 1
    There are two questions here. The first asks how it is represented in Java (Bytecode). The second asks if there are differences in performance and bytecode (i assume size is the concerning factor here). – Shaun Jan 11 '10 at 17:09
  • 3
    Any compiler that doesn't recognize that optimization won't make it very far on the market ;) – Carl Smotricz Jan 11 '10 at 17:10
  • Don't waste your time wondering things like this. Instead, learn more about the things that cause REAL performance problems in real life. No one has ever saved their application from a performance code-red by changing an `if (foo == false)` to an `if (!foo)`. – Kevin Bourrillion Jan 11 '10 at 19:06
  • foo == false is bad style, almost as bad as foo == true or b ? true : false. – starblue Jan 11 '10 at 19:53
  • @Kevin: you rely heavily on the assumption that I'm asking this because of performance, which is wrong. The question is more about the workings of and specifications for compilers. Also, I would appreciate it if you would provide examples of "the things that cause REAL performance problems in real life." – Pops Jan 11 '10 at 20:36
  • @Lord Torgamus Note that the title of your question very specifically asks about performance. – ColinD Jan 12 '10 at 01:17
  • @Colin: Fair enough. In this case, performance is the implicit result of compiler behavior, but your point is valid. Also, my comment about wanting examples was serious. – Pops Jan 12 '10 at 04:42

8 Answers8

44

The JLS would specify the required behavior of the statements. However, how they are implemented is an implementation detail of the compiler and the JVM.

In practice, any compiler worth its salt should emit the same bytecode for those statements. And even if not, the JVM would optimize them properly.

Also, a better way to answer this, is to check for yourself, using javap:

  1. Compile a Test.java with the following content:

    class Test {
        void equals(boolean f) {
            if (f == false) {}
        }
        void not(boolean f) {
            if (!f) {}
        }
    }
    $ javac Test.java
    
  2. De-assemble it:

    $ 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
    
    }
    

UPDATE: Responding your question about the "academic" question. As mentioned above, the JLS is only concerned with the behavior. There is nothing in the standard that actually specifies how it should be implemented (well, JVMS provides a lot of guidance).

As long as the compiler preserves the same identical behavior, the compiler is free to implement it different, with possibility different runtime performance.

notnoop
  • 58,763
  • 21
  • 123
  • 144
12

The compiler should resolve to the same code internally, so there is no difference.

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
0

try decompiling the byte code and see how different the code looks. I would guess the compile would resolve them almost identically and any slight difference would result in negligible performance difference.

gingerbreadboy
  • 7,386
  • 5
  • 36
  • 62
  • 1
    or even take a look at the byte code itself http://stackoverflow.com/questions/800916/should-i-look-at-the-bytecode-that-is-produce-by-a-java-compiler – gingerbreadboy Jan 11 '10 at 17:14
0

OK, a more complete answer:

I would be very surprised if any compiler generated different bytecode for these variations. For anyone who's interested, it should be easy enough to check using a disassembler.

Given that both expressions (most probably) compile to the same bytecode, I expect no difference in size or performance.

Carl Smotricz
  • 66,391
  • 18
  • 125
  • 167
0

The JLS says that

the expression in an if block is evaluated, then the result of that expression is compared to true

In both the not case and the compare object cases, an expresion needs to be evaluated and then compared to true. If you were checking a value rather than performaing an operator on it, there may be a theoretical performance benefit as the expression evaluation becomes a no op.

But in this case, I'd expect the JIT to produce the same bytecode for both expressions.

Robert Christie
  • 20,177
  • 8
  • 42
  • 37
0

There should be no difference in the bytecode generated for those two results and if it did unless you are creating code for a device with very limited resources (in which case you should not be writing in Java) than the difference would be negligible and you should decide which of the two ways of writing this code is a more obvious solution.

RHicke
  • 3,494
  • 3
  • 23
  • 23
0

Thinking about micro-optimizations is in almost any cases a waste of time and leads to thinking in wrong ways...

helpermethod
  • 59,493
  • 71
  • 188
  • 276
0

I asked a similar question regarding C++ / VS2008.

Would VS2008 c++ compiler optimize the following if statement?

To avoid = vs == typos in C++, you would tend to write

if (NULL == ptr) { ... }
if (false == boo) { ... }
if (20 == num) { ... }

etc.

This is slightly less readable until you get used to it.

Community
  • 1
  • 1
Hamish Grubijan
  • 10,562
  • 23
  • 99
  • 147