A few days ago, a friend told me that he was asked this question in an interview:

In the for loop, should I ++ or ++ I be used?

Java 1.8.0_261-B12

Hearing this, I feel that the interviewer is really a bit not according to the routine card, put a good Essay, net whole some unitary things. Before leaving, my friend asked the interviewer what the answer to this question was. The interviewer did not give a clear answer, but asked him to think about it from the perspective of the efficiency of the program execution.

Well, now that this question is out of the question, let’s see what we can do for you.

1, the train of thought

As mentioned earlier, the rogue interviewer said to think in terms of executive efficiency, so let’s set aside semantic distinctions and look for clues in terms of efficiency beyond performance results. Recall that we mentioned in our previous CAS article that neither postincrement I ++ nor preincrement ++ I are atomic operations, so what does it actually look like in execution? Next, let’s do a wave of analysis from the bottom up, from the point of view of bytecode instructions.

I++ performs the procedure

Write a simple piece of code with only assignment and increment at its core:

public static void main(String[] args) { int i=3; int j=i++; System.out.println(j); }Copy the code

Let’s decompile the bytecode file using JavAP and see the bytecode instructions in action:

Is it a little hard to understand? It doesn’t matter, let’s take a graphical look at how this works and explain how obscure bytecode instructions operate on the data structure in a stack frame. For brevity, only the important operand stacks and local variables are listed in the diagram.

Int I =3 int I =3 int I =3 int I =3 int I =3

Int j=i++ int j=i++ int j=i++

It is important to note in the figure above that IINC can directly update the values of variables in the local variable table without pushing values onto the operand stack. In the above process, excluding other operations such as assignment, i++ actually executes bytecode instructions:

2: iload_13: iinc 1, 1
Copy the code

If translated into Java code that we can understand, it can be interpreted as:

int temp=i; i=i+1;Copy the code

That is, in addition to the necessary increment, a new local variable is introduced. Now let’s look at the implementation of ++ I.

++ I Execution process

Let’s make a small change to the code above, just replace I ++ with ++ I, and let’s see how ++ I works.

public static void main(String[] args) { int i=3; int j=++i; System.out.println(j); }Copy the code

Also, decompile bytecode files with Javap:

Int j=++, int j=++, int j=++, int j=++, int j=++, int j=++, int j=++, int j=++

Discard the assignment, and the actual execution of ++ I is a single line of bytecode instruction:

2: iinc 1, 1
Copy the code

When translated into understandable Java code, ++ I is actually executed in a local variable:

i=i+1;
Copy the code

So, using ++ I does take one step less than I ++, introduces one less local variable, and is actually a little bit more efficient than using ++ I in the same scenario.

So back to the question at the beginning, which of the two methods of increment is more efficient when applied to the for loop? Does that still apply to the for loop? Hold on, let’s move on.

Increment in the for loop

Here are two pieces of code containing the for loop, using I ++ postincrement and ++ I preincrement respectively:

Public class ForIpp {public static void main(String[] args) {for (int I = 0; i < 5; i++) { System.out.println(i); Public class ForPpi {public static void main(String[] args) {for (int I = 0; i < 5; ++i) { System.out.println(i); }}}Copy the code

As usual, decompile the bytecode file directly and compare the execution of the instruction:

At this point, the interesting thing is that both programs execute exactly the same part of the bytecode instruction. Leaving aside why this is the case, let’s take a look at the bytecode instructions in a diagram:

You can clearly see that iINC is executed directly when it increments, and iloAD is not executed before, that is, both pieces of code execute ++ I. There is an even easier way to verify this process. You can open the bytecode file directly with IDEA and see the same pre-increment method used in the final for loop.

So why does this happen? The bottom line is that the Java compiler optimizes code. If there is no assignment in either increment, it optimizes the code in one way, as in the following two methods:

void ipp(){ int i=3; i++; }void ppi(){ int i=3; ++i; }Copy the code

The bytecode instructions for final execution are:

0: iconst_31: istore_12: iinc 1, 15: return
Copy the code

As you can see, in this particular case, the code was optimized by the compiler to keep the semantics intact and to make the code run more efficiently by transforming the syntax. So going back to our initial question, we can conclude that in a for loop, compilation optimizations performed by the JVM, whether I ++ or ++ I, end up executing ++ I, so the efficiency is the same.

So, in the future, when an interviewer asks you about the efficiency of I ++ and ++ I in the for loop, be confident and throw the answer in his face.

PS: In case you can’t find this article, please click “like” to browse and find it.