“This is the 28th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

This column is aimed at Java interview questions to create a column, each article corresponds to a common interview questions, hope to help you.

This article will introduce the self-increasing variable, which is a common question in the interview. It is difficult to say, easy to say and not easy. It requires the interviewer to think calmly and judge the priority between the correct symbols.

Take a look at the following program:

	@Test
	public void test1(a){
		int i = 1;
		i = i++;
		int j = i++;
		int k = i + ++i * i++;
		System.out.println("i = " + i);		
		System.out.println("j = " + j);		
		System.out.println("k = " + k);
	}
Copy the code

Before you rush to run to see the answer, first analyze yourself, this program will output what?

So let’s first analyze the simplest variable, what does j output? There is only one place in the program to change the value of variable j:

int j = i++;
Copy the code

This is hard to believe that you, I believe that we have not been less pit of this kind of problem, but a fall into the pit, a gain in wisdom. For this line of code, since the increment ++ is to the right of variable I, j must have the value of 1.

As for what the values of I and j are, let me give you the answer:

i = 4
j = 1
k = 11
Copy the code

Did any of you feel doubtful about life after reading the answer? No words that should congratulate you first, you have enough solid basic skills, this problem did not stumped you.

There are also students who look at the answer and know they got it wrong, but look back at the code and suddenly understand, and those of you who believe that you can also get it right, just because you are careless, so you have to be very careful when you do this type of problem, because there are holes in these problems waiting for you to jump.

There should be some students are in a state of continued meng, don’t worry, this article is tailored for you, after reading this article, in dealing with this kind of topic must be “easy”.

The code analysis

As for the value of j, we have already analyzed it, so let’s focus on the variables I and K.

First we define a variable I = 1, and then we assign it:

i = i++;
Copy the code

Because the increment is on the right hand side, the value of I is 1, and that’s what we did with j, so why on earth does the increment on the right hand side mean the value of I must be 1?

Let’s start with a concept called stack frames.

A stack frame is a data structure used to support vm method invocation and method execution. It is the stack element of the VM stack in the data area when the VM runs. A stack frame stores information about a method’s local variogram, operand stack, dynamic linkage, and method return address.

Each method from the call to the completion of the process, corresponding to a stack frame in the virtual machine stack from the stack to the stack process.Copy the code

When the program executes int I = 1; After that, the value of variable I is stored in the local variable table (the local variable table is a group of variable value storage space used to store method parameters and local variables defined within the method).

When the program executes the second line of code I = I ++; The Java virtual machine uses the operand stack as its workspace — most instructions pop data from here, perform operations, and then push the results back onto the operand stack.

Such as the operating here, it will first I press values into the operand stack, I on the right now, this time I value of local variables to 2, perform assignment operation at this time, need to eject the values in the operand stack again assigned to the I, so that the values in the operand stack 1 are covered the variable I, so I still 1 calculation in the same way (j).

If I = ++ I, the value of I is 2, because this code increments the value of I in the local variable table to 2, and then pushes it onto the operand stack, and then performs the assignment, and the value pops up to 2.

After the first two lines of code are executed, the value of I is 1, and then the third line is executed:

int j = i++;
Copy the code

Although this line of code does not change the value of j, the value of I in the local variable table does change, and I becomes 2.

Look at line 4:

int k = i + ++i * i++;
Copy the code

This is also the most critical line of code, let’s draw a picture to understand:

First, there is a variable k in the table of local variables, whose value is the result of the operation on the right-hand side of the equal sign.

The value of I is first pushed onto the operand stack:Multiplication and division followed by addition and subtraction, executed first++i * i++And see first++iOperation, since the increment sign is on the left, so increment first, then the value of I in the local variable table is 3, and then push it into the operand stack:To performi++Operation (increment takes precedence over multiplication), in this case, since the increment is on the right, the value of I is pushed into the operand stack, and then increment:The next step is to multiply by popping two numbers in the operand stack:
3 3 = 9 3 times 3 is 9
The operation is not finished, and 9 is pushed back on the stack:Then perform an addition operation to pop the two numbers on the stack together:
9 + 2 = 11 9 plus 2 is 11
Again, 11 is pushed back into the stack before the operation is finished:Finally, the assignment operation is performed to pop up the value 11 in the stack and assign the value to the variable K in the local variable table. At this time, the value of K is 11.

So that’s how you compute the variables I and k.

The whole calculation process can be known by looking at the bytecode file and entering the command in the Dos window:

Javap verbose class nameCopy the code

The Dos window will print out the specific execution process, and here I post the most important part:

public static void main(java.lang.String[]);
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=3, locals=4, args_size=1
       0: iconst_1
       1: istore_1
       2: iload_1
       3: iinc          1, 1
       6: istore_1
       7: iload_1
       8: iinc          1, 1
      11: istore_2
      12: iload_1
      13: iinc          1, 1
      16: iload_1
      17: iload_1
      18: iinc          1, 1
      21: imul
      22: iadd
Copy the code

Iconst_1: loading a constant onto the operand stack; iconst_1: loading a constant onto the operand stack The instruction labeled 1, istore_1, means to pop a value from the operand stack into the local variable table, so the two instructions together complete the statement int I = 1.

Then we have iload_1, which loads a local variable into the operand stack, iinc, which adds a value to the specified variable, and then iload_1, which adds a value to the specified variable: Istore_1, which pops a value from the operand stack into the local variable table. Together, these three instructions complete the statement I = I ++.

I’m not going to analyze this, but you can see for yourself whether it’s going to run the same way.

Something to watch out for

I++ is assigned first and then incremented; ++ I is incremented first, then assigned. In fact, assignment is always performed last whether the increment operator is on the left or the right, not first when the increment operator is on the right.

Different positions of increment symbols lead to different values, which are caused by the operand stack. If the increment character is on the left side, it increases first and then pushes onto the stack. At this time, the pop-up value must be the increment value. If the increment character is on the right, it is pushed first and then incremented, and the pop-up value is the same as the original value, which is the root cause of this problem.

conclusion

Through this problem, the following points are summarized:

  • Assignment is always last
  • The values to the right of the equals sign are pushed into the operand stack from left to right
  • Which one to calculate first depends on the precedence of the operator
  • The increment and decrement operations modify the value of a variable directly, without going through the operand stack
  • Until assignment, the temporary result of the operation is still stored in the operand stack