Is it better to assign Boolean.TRUE/Boolean.FALSE or true/false to a boolean primitive variable?

While doing some code reviews I stumbled upon this:

People usually assign Boolean.TRUE or Boolean.FALSE value to a boxed boolean variable but use true/false for primitive variables. What is the best way for this?

According to an architect I worked with – he said that every time you assign true/false to a variable a new instance of Boolean is created. We can skip that if we assign the boolean variable to the static instances – Boolean.FALSE/Boolean.TRUE. If the variable is primitive an auto-unboxing is done.

Is the auto-unboxing faster than the initialization of a boolean variable? The differences are not big and I think this is just a micro-optimisation of the code but I wanted to learn more about this.

Answer

You are right that the performance concerns are mostly a distraction.

To understand what is going on, let’s look at how primitives and their boxes are modeled in the Java type system.

When C extends D, this means that a C is-a D, or that C is a subtype of D. When assigning an Integer to Number, no conversion is required, because an Integer is-a Number. Under the hood, both Integer and Number are represented by pointers (object references) and the assignment is just a pointer copy.

The relationship between boolean and Boolean is different, though. There is no extends; there is no is-a. Instead, there are boxing unboxing conversions, which get applied in certain contexts (e.g., assignment, method parameters.) Their representations are different. So when you convert between boolean and Boolean, the form changes (from a direct representation of the boolean value, to a pointer to a heap node containing an object header and a boolean payload.) This is why people warn you about “the performance cost”; it’s not just copying one word. (That said, if this is the performance bottleneck in your program, you’ve got bigger problems — namely that your program doesn’t do very much.)

When you assign

boolean b = true;

or

Boolean bb = Boolean.TRUE;

the types on both sides of the = are the same; boolean in the first example, Boolean in the second. When you do

boolean b = Boolean.TRUE;

or

Boolean bb = true;

the types are different, and there is a conversion required. The compiler silently translates these to:

boolean b = Boolean.TRUE.booleanValue();

and

Boolean bb = Boolean.valueOf(true);

In the specific case of boolean, the performance concerns are even less relevant than for other primitives, since there are only two boolean values, and the constants Boolean.TRUE and Boolean.FALSE are interned.

If your architect gave you this advice primarily on performance concerns, then he/she was misguided. If their advice was motivated more by simplicity — that it is equally easy to use a value of the correct type that requires no conversion — this is sensible.

Leave a Reply

Your email address will not be published. Required fields are marked *