BaiFan
文章目录
  1. 1. 背景知识
    1. 1.1. ILOAD
    2. 1.2. ISTORE
    3. 1.3. IINC
    4. 1.4. i++ VS ++i
  2. 2. 实例讲解
    1. 2.1. i=i++
    2. 2.2. i=++i

本文在JVM指令层次讲解i=i++之后,i的值不变的问题。.

背景知识

JVM在方法体中的操作指令,一部分是直接作用stack栈,也有一些部分是直接操作Local Variable(本地变量区/局部变量区)。

简单的介绍两个指令

ILOAD

将一个整数常量push到方法栈中。

ILOAD n 执行前stack

index value
0
1

ILOAD n 执行后stack

index value
0
1 n

而本地变量区没有变化。

ISTORE

将一个整数常量pop出方法栈,并将该常量值赋值给本地变量区(Local Variable)。

ISTORE n 执行前stack

index value
0
1 x

ISTORE n 执行后stack

index value
0
1

ISTORE n 执行前 Local Variable

index value
0
n

ISTORE n 执行后Local Variable

index value
0
n x

IINC

将一个本地变量区(Local Variable)的整数常量值加1。

本地方法栈无变化。

ISTORE n 执行前 Local Variable

index value
0
n x

ISTORE n 执行后Local Variable

index value
0
n x + 1

i++ VS ++i

在平时的讲解中,”i++“ 这条指定会在完成整个语句运算后执行,”++i“ 这条指令会在整个语句运算前执行。

实例讲解

i=i++

现在有一段代码如下

1
2
3
4
5
public void afterPlus() {
int i = 0;
i = i++;
Assert.assertEquals(0, i);
}

编译成指令后,其中i=i++的指令如下

1
2
3
ILOAD 1
IINC 1 1
ISTORE 1

应该有部分同学明白了,ILOAD指令先把i的原始值先被加载到了stack中,
然后IINC指令将本地变量中的i进行了+1操作,但是栈上的i还是原始值。
然后ISTORE指令又将栈上的i的原始变量值付给了本地变量i。
所以i相当于没做操作。

i=++i

代码如下

1
2
3
4
5
6
public void beforePlus() {
int i = 0;
i = ++i;
Assert.assertEquals(1, i);
}
}

编译成指令后,其中i=i++的指令如下

1
2
3
IINC 1 1
ILOAD 1
ISTORE 1

IINC指令将本地变量中的i进行了+1操作,
ILOAD指令先把i+1的值先被加载到了stack中,
ISTORE指令stack上的新值赋值付给了本地变量i,
所以本地变量是+1后的值。

文章目录
  1. 1. 背景知识
    1. 1.1. ILOAD
    2. 1.2. ISTORE
    3. 1.3. IINC
    4. 1.4. i++ VS ++i
  2. 2. 实例讲解
    1. 2.1. i=i++
    2. 2.2. i=++i