Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Ternary vs. if with big objects

Tags:

java

The ternary operator normally just is a subject to philosophical discussions: whether

a=b>5?1:0;

is more readable, faster, cooler to

if(b>5) { a=1; } else {a=0;}

(take or leave the curly braces) I normally don't care. I like my ternary operator. But we had a discussion concerning this piece of code:

BigObject myBigObject=null;
...
do {
   myBigObject=
     myBigObject==null?
     createBigObject():
     myBigObject;
...
} while(manyIteration);

Colleague claimed that this construct will create the myBigObject will be copied every loop (except the first) which will waste precious time and memory and that he found the case where the ternary operator is useless. the only way is:

do {
     if(myBigObject==null)
       myBigObject=createBigObject();
...
} while(manyIteration);

I argued that the clever compiler will see that the object is assigned to itself and will optimize it out.

But who is right?

like image 546
Joachim Weiß Avatar asked Jul 23 '26 13:07

Joachim Weiß


2 Answers

The definite answer lies in section 15.25 of the JLS (emphasis mine):

The resulting boolean value is then used to choose either the second or the third operand expression: - If the value of the first operand is true, then the second operand expression is chosen. - If the value of the first operand is false, then the third operand expression is chosen.

The chosen operand expression is then evaluated and the resulting value is converted to the type of the conditional expression as determined by the rules stated below.

This conversion may include boxing or unboxing conversion (§5.1.7, §5.1.8).

The operand expression not chosen is not evaluated for that particular evaluation of the conditional expression.

This means both expressions are not always evaluated: only the one that needs to be is. So actually, none of you are right.

  • You're wrong because it is not the compiler being clever: it is specified by the language itself;
  • Your collegue is wrong because the expression won't be evaluated if need not be.

In the code

myBigObject = myBigObject == null ? createBigObject() : myBigObject;
              ^-----------------^   ^---------------^             
           this is true the 1st time, hence that ^ is evaluated


myBigObject = myBigObject == null ?    createBigObject()     :        myBigObject;
              ^-----------------^                              
           this is false the 2nd time, hence that ^ is NOT evaluated, that ^ is

Notice that what is executed is just assigning myBigObject to itself, which does not create a new object.

like image 50
Tunaki Avatar answered Jul 25 '26 04:07

Tunaki


Colleague claimed that this construct will create the myBigObject will be copied every loop (except the first) which will waste precious time and memory and that he found the case where the ternary operator is useless.

You should note that myBigObject is a reference to an object. This means it is 4 bytes on most JVMs and a redundant copy isn't going to make a big difference.

I argued that the clever compiler will see that the object is assigned to itself and will optimize it out.

Possibly, though I don't see it will make much difference either way.

While a compiler can remove redundant code, it is harder for a human to remove redundant code. In general we code with a purpose. When code has no purpose it is much harder to come to that conclusion. I suggest you avoid confusing anyone who has to read/maintain the code in the future.

As ever, when discussing performance, you should first consider clarity. How surprising in this construct and how easy is it to maintain.

The cost of a redundant assignment (which may or may not be optimised away) is nothing compared with the cost of even an easy to fix bug (never mind a hard to fix one)

You should focus on what is clearer (which is subjective) and not worry about micro-tuning the code unless you have a profiler which indicates this line is a performance issue.

For me, this is clearer, but even if it were slower, I would still argue it is clearer and easier to understand what it is doing.

if (myBigObject == null)
    myBigObject = createBigObject();

The fact you have already had to have a discussion but what that code is really doing, means you have spent more time than you can possibly recover.

In short, developer efficiency is usally more important than computer efficiency.

like image 39
Peter Lawrey Avatar answered Jul 25 '26 04:07

Peter Lawrey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!