i++是先算后加,++i是先加后算,这个在我们学习循环就已经知道的东西,到底蕴含了什么呢?
我们来看一段代码

int i1=10;
int i2=i1++;

int i3=10;
int i4=++i3;

int i5 = 10;
i5 = i5++;

int i6=10;
i6 = ++i6;

int i7=10;
int i8 = i7++ + ++i7;
i7=10;
int i9 = ++i7 + i7++;

稍稍有点眼花缭乱,没关系,很简单,认真看看就能看懂,那么他们输出什么呢?

i1=:11
i2=:10
i3=:11
i4=:11    //直到i4大家都应该懂
i5=:10    // i5以后可能有点难度
i6=:11
i7=:12
i8=:22
i9=:22

要解释i5,i6,i8,i9,需要从java的字节码角度去探索

栈结构

我们知道,java虚拟机中对象一般在堆中,而常量运算一般在栈中(这里是简略描述,真实比这个复杂)
上面的所有运算都是在栈中完成的,栈的基本单位是栈帧,而一个方法所占用的空间就是一个栈帧,上面只有一个main方法,所以占用一个栈帧
如图

每个栈帧对应一个方法,包含五个内容,但是由于我们这道题只涉及局部变量表和操作数栈,我们只看这两个

内容 接受
局部变量表 记录方法中变量的值
操作数栈 记录运算过程中的中间变量

局部变量表可以看做是菜谱,操作数栈可以看做是做菜的中间状态

字节码

现在我们知道,我们的代码将会在栈帧中的局部变量表和操作数栈中发生事情,那如何发生?,就是通过字节码指令运行,字节码由java代码编译而来,在idea中安装jclasslib插件即可查看
字节码如下
先了解以下4行代码

  0 bipush 10   //将10压入操作数栈
  2 istore_1    //将栈顶的数保存到局部变量表的1位置处
  3 iload_1		//将局部变量表1位置处的值取出
  4 iinc 1 by 1 //将局部变量表中1位置处的值自增1

好,准备工作做完了,现在开始分析

前6个


int i1=10;
int i2=i1++;
int i3=10;
int i4=++i3;
int i5 = 10;
i5 = i5++;
int i6=10;
i6 = ++i6;

字节码如下,字节码前面的数字表示的是地址,不是代码行数

0 bipush 10      //压入10到栈中
2 istore_1		  //将栈顶的10保存到局部变量表的1处(简称i1)
3 iload_1	      // 复制i1并取出
4 iinc 1 by 1    //自增位于局部变量表中的i1 
7 istore_2       //将取出的i1放到局部变量表的2处(简称i2)
//注意,这里是先取出再自增,取出的i1还是原值,所以i2依旧为10

8 bipush 10
10 istore_3
11 iinc 3 by 1     //这里是先自增再取出
14 iload_3
15 istore 4        //i4为10

17 bipush 10
19 istore 5        
21 iload 5         //i5先取出
23 iinc 5 by 1     //局部变量表处再自增
26 istore 5        //又将取出的值存回去,所以先取出的10覆盖了自增的11
28 bipush 10
30 istore 6
32 iinc 6 by 1    //i6先自增再取出
35 iload 6
37 istore 6       // 所以取出的是11,覆盖的也是11

最后两个

int i7=10;
int i8 = i7++ + ++i7;
i7=10;
int i9 = ++i7 + i7++;

首先我们明确,自增操作符++的优先级高于 运算符+号
而且是从左到右运算
来看字节码

 39 bipush 10
 41 istore 7
 43 iload 7
 45 iinc 7 by 1
 48 iinc 7 by 1
 51 iload 7
 53 iadd
 54 istore 8
 
 56 iinc 7 by 1
 59 iload 7
 61 iload 7
 63 iinc 7 by 1
 66 iadd
 67 istore 9

这就是i7++与++i7的字节码混合,如图

i7++中局部变量表处自增时,由于没有执行=号,所以没有存回去,这个时候,轮到了++i7,++i7执行了自增后,实际上局部变量表中的i7此时已经是12了

所以23行 iload 7的值为10,但是26行iload 7的值为12,综合下来,还是22

至于i9,一样的道理,可以自己探索哦

这道题就像一道门,可以窥探java虚拟机的复杂内容,深入java虚拟机,做一个不止会搬砖的人~