Testing booleans readably in Java

This surely is not the first or last musing on how to write ifs with boolean variables in Java. I normally just write it as IDEA suggests with its “simplify” correction (inspection is called “Pointless boolean expression”). However I never criticized anyone yet for their style of comparing the boolean variable to the literal true or false. I do some code review that is a part of my role in the team and while I communicate most of my observations this I just quick fix with IDEA and go on. “Whatever your taste is, my word is the final word anyway.”

But this Friday one of the developers came back to me and said “hey, I do it so it is more readable”. And readable is the word I hear to pretty strong. I have no problem to read both these styles and I prefer the minimal one. While I’m clearly decided about comparing to true (utter waste and nicely exaggerated here), comparing to false is indeed a bit different. There you can argue that that exclamation is not always so visible.

It’s not always as easy as “short is better” – often on the contrary. Prominent example being the assignment in the middle of the expression – in a ternary expression for instance. I’d go for ifs and an assignment per line all the time. But while here we are mostly aligned when it comes to (checked == false) versus (!checked) we developers are not so unanimous.

The aforementioned link to stackoverflow inspired me to check how various cases are compiled. I made a class:

public class BooleanEqualityTest {
   boolean bb;

   private void a() {
       boolean b = bb;
   }
   private void b() {
       boolean b = bb == true;
   }
   private void c() {
       boolean b = (bb == true) == true;
   }
   private void x() {
       boolean b = !bb;
   }
   private void y() {
       boolean b = bb == false;
   }
   private void z() {
       boolean b = bb == false == false;
   }
}

After compile I went to the output directory and ran the command:

javap -private -c BooleanEqualityTest

And the result was:

Compiled from "BooleanEqualityTest.java"
public class BooleanEqualityTest extends java.lang.Object{
boolean bb;

public BooleanEqualityTest();
 Code:
  0:    aload_0
  1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
  4:    return

private void a();
 Code:
  0:    aload_0
  1:    getfield    #2; //Field bb:Z
  4:    istore_1
  5:    return

private void b();
 Code:
  0:    aload_0
  1:    getfield    #2; //Field bb:Z
  4:    iconst_1
  5:    if_icmpne    12
  8:    iconst_1
  9:    goto    13
  12:    iconst_0
  13:    istore_1
  14:    return

private void c();
 Code:
  0:    aload_0
  1:    getfield    #2; //Field bb:Z
  4:    iconst_1
  5:    if_icmpne    12
  8:    iconst_1
  9:    goto    13
  12:    iconst_0
  13:    iconst_1
  14:    if_icmpne    21
  17:    iconst_1
  18:    goto    22
  21:    iconst_0
  22:    istore_1
  23:    return

private void x();
 Code:
  0:    aload_0
  1:    getfield    #2; //Field bb:Z
  4:    ifne    11
  7:    iconst_1
  8:    goto    12
  11:    iconst_0
  12:    istore_1
  13:    return

private void y();
 Code:
  0:    aload_0
  1:    getfield    #2; //Field bb:Z
  4:    ifne    11
  7:    iconst_1
  8:    goto    12
  11:    iconst_0
  12:    istore_1
  13:    return

private void z();
 Code:
  0:    aload_0
  1:    getfield    #2; //Field bb:Z
  4:    ifne    11
  7:    iconst_1
  8:    goto    12
  11:    iconst_0
  12:    ifne    19
  15:    iconst_1
  16:    goto    20
  19:    iconst_0
  20:    istore_1
  21:    return

}

What does it mean? Every == true is adding something to the code, but the first == false produces the same bytecode as the not operator itself (!). Every other == false is then adding to the code just like any other comparison. While HotSpot may do wonders with the code later I still consider it a waste and completely unnecessary – except for the single == false – and that was the case where I hesitated just a bit.

Now I will probably stop correcting this case, though I will keep writing !checked instead of checked == false. The only thing I don’t like about it all right now is that the inspection in IDEA cannot be set to ignore just this case. I can still set it to weak-warning, but that’s just not the same, you know. 🙂

What is your opinion on this matter? Do you have similar cases where you’re just not convinced which way is the cleaner one?

Update 31.10.2011: I decided after all. I’ll go for !(…) like this:

if (!(checked)) ...

This is quite clear, ! is nicely visible and redundant parentheses are not warning. After all, parentheses are traditionally used to make expressions readable. 🙂

Advertisements

About virgo47
Java Developer by profession in the first place. Gamer and amateur musician. And father too. Naive believer in brighter future. Step by step.

2 Responses to Testing booleans readably in Java

  1. Esben Jensen says:

    I think it’s odd if the Java compiler can’t reduce those excessive comparisons. Normally I wouldn’t write something like that, but there might be fringe cases where it adds readability, and I would expect a compiler to crunch it into a simpler result. Thats what compilers are for after all – correcting the human weakness of making ineffecient statements. 😉

    In terms of readability I never liked the C/Java ! operator, it can be easy to miss in a block of code, especially when followed by an unfortunate combination of letters.

    if(icecream)

    if(!icecream)

    I personally find that adding a space does wonders and in most cases removes the need to compare to ‘false’.

    if(! icecream)

    In this case I think the ‘not’ operator of other languages is handy, even though I’m not exactly a fan of the ‘plain English’ philosophy of language design.

    • virgo47 says:

      icecream is nice example 🙂

      I agree that compiler should do something with == true or with double == false. I didn’t actually realize that == false changes the result every time you add it, but I just examined the compiler output, so it’s not a problem here.

      I write:

      if (!icecream)

      I always put space after the keywords (for, if, while) – this is also in line with Sun’s original recommendations. I don’t have problem to spot ! at the beginning of field/local variable, but I don’t love this operator either. You can also go for:

      if (!(icecream))

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s