Firstly, the performance advantage of using any one over the others is most likely to be too small to be relevant1. Code simplicity / readability / maintainability is a far more important ... in the vast majority of cases.
Or is it optimized on compiler level and all true
and false
are replaced by references to the static objects to save memory?
There's a fundamental misunderstanding here. The boolean
type is a primitive (not reference) type. The true
and false
values cannot be replaced with references. Furthermore, the space used to hold representations of true
and false
depends on the context. It is often a single byte ... which is significantly less than the 8 bytes needed to store a reference on a 64-bit JVM (with oops compression disabled). So that "optimization" would NOT save memory even if it was technically possible.
None of your examples involve creation of Boolean
instances2 so we can discount that from our performance analysis.
# Example 1
boolean isItTrue(arg){
return true;
}
This one will be equal to or faster than all of the others because it simply entails setting a register to zero.
# Example 2
Boolean isItTrue(arg){
return Boolean.TRUE;
}
Taken in isolation, this has to load a static reference from memory, rather than zero a register. However, the JIT compiler may be able to optimize this away in some circumstances.
# Example 3
Boolean isItTrue(arg){
return true;
}
On the face of it, this involve a call to Boolean.valueOf(true)
to "box" the true
, but the JIT compiler should be able to optimize it to the same code as the previous one by inlining the call.
# Example 4
boolean isItTrue(arg){
return Boolean.TRUE
}
On the face of it, this involves a call to Boolean.booleanValue(Boolean.TRUE)
to "unbox" the Boolean
. This call can be inlined. It is also possible that the JIT compiler can avoid loading the reference to the Boolean
object and fetching its value field.
In summary, the relative performance of your 4 examples depends on how successful the JIT compiler is in optimizing. That will depend on the context, the specifics of the JIT compiler, the JVM settings, and so on. In theory, the JIT compiler could produce the same (optimal) code for all of them. In practice, the difference will be insignificant in nearly all cases. (And this is not a practical example anyway.)
1 - This benchmark unwittingly demonstrates this. If the results it presents are to be believed, then the performance difference between the best and worst versions is less than 1 ns per call.
2 - It is theoretically possible that 3 of the 4 could trigger the initialization of the Boolean
class AND that your application wouldn't otherwise have done that. In that highly unlikely event, your entire application will allocate 2 objects that wouldn't otherwise have been allocated. The initialization will probably take a few microseconds, and consume a few bytes of RAM (less than 50) in the long term. This is irrelevant in practice.