i++
When we first learned i + + and + + i, we always kept in mind that i + + was used first and then added with 1, + + i was used first and then added with 1. We have been carrying bricks like this for a long time (this conclusion is no problem of course), so have i. Until i see the following question.
public static void func(){ int i=0; for(int j=0;j < 100;j++){ i = i++; } Stystem.out.println(i);//Print what??? }
I think it's printed 100, no doubt, I'm wrong. By the way, there is no such article.
It seems that I'm still too busy. Look at the bytecode!
0 iconst_0 1 istore_0 2 iconst_0 3 istore_1 4 iload_1 5 bipush 100 7 if_icmpge 21 (+14) 10 iload_0 11 iinc 0,1 14 istore_0 15 iinc 1,1 18 goto 4 (-14) 21 getstatic #2 <java/lang/System.out> 24 iload_0 25 invokevirtual #3 <java/io/PrintStream.println> 28 return
Among them, 10-14 corresponds to the bytecode of i=i + +. It is strongly recommended to install the Jclasslib plug-in for IDEA, so that it is more convenient to specify the meaning of mnemonics.
- iload_0: push the value of the local variable with index 0 of the local variable array of the current stack frame to the operand stack.
- iinc 0,1: increments the local variable with index 0 by 1.
- istore_0: pops the value from the operand stack (recorded as val) and sets the local variable value with index 0 to val.
After reading these three mnemonics, we will find that although the value of iinc is increasing, it is not set to i, so the value of i has not changed, and i + + has no effect at all. The dynamic diagram is as follows:
Well, that's it. i was changed and then overridden by the stack value_
++i
Now let's change the question to + + i.
public static void func(){ int i=0; for(int j=0;j < 100;j++){ i = ++i; } Stystem.out.println(i);//Print what??? }
The corresponding bytecode is as follows.
0 iconst_0 1 istore_0 2 iconst_0 3 istore_1 4 iload_1 5 bipush 100 7 if_icmpge 21 (+14) 10 iinc 0,1 13 iload_0 14 istore_0 15 iinc 1,1 18 goto 4 (-14) 21 getstatic #2 <java/lang/System.out> 24 iload_0 25 invokevirtual #3 <java/io/PrintStream.println>
It's still the same 10-14 lines,
So i can be changed, print 100.
Hybrid operation
In the written test questions of i + + and + + i, they are often mixed, a pile of + headache. For example: i = (i + + + (i + + + + + + + i) + (+ + i);. Let's start with a simple one (i = i + + + + + + i;), otherwise the bytecode will be confused. In fact, the answer is very simple, but we need to understand it better through its bytecode. The bytecode is as follows.
0 iconst_0 1 istore_0 2 iload_0 3 iinc 0,1 6 iinc 0,1 9 iload_0 10 iadd 11 istore_0 12 getstatic #2 <java/lang/System.out> 15 iload_0 16 invokevirtual #3 <java/io/PrintStream.println> 19 return
We only need to focus on lines 2-11. The values and stacks corresponding to these steps are shown in the figure below. This is also the purpose of this paper. Let's learn a mnemonic first.
iadd
Both value1 and value2 must be of type int. The values are popped from the operand stack. The int result is value1 + value2. The result is pushed onto the operand stack.
The result is the 32 low-order bits of the true mathematical result in a sufficiently wide two's complement format, represented as a value of type int. If overflow occurs, then the sign of the result may not be the same as the sign of the mathematical sum of the two values.
Despite the fact that overflow may occur, execution of an iadd instruction never throws a run-time exception.
Well, iadd After adding, the value will be pushed into the stack, remember!!
Difficult mode
Let's draw it I = (I + + + (I + + + + + + I) + + + I); see if the examiner can draw the process map. The bytecode is as follows.
0 iconst_0 1 istore_0 2 iload_0 3 iinc 0,1 6 iload_0 7 iinc 0,1 10 iadd 11 iinc 0,1 14 iload_0 15 iadd 16 iinc 0,1 19 iload_0 20 iadd 21 istore_0 22 getstatic #2 <java/lang/System.out> 25 iload_0 26 invokevirtual #3 <java/io/PrintStream.println> 29 return
We just need to focus on lines 2-21.