入门理解
i++:先操作再自增
++i:先自增再操作
这个理解一般是没毛病的,但是如果遇到下面这个问题,这个理解就不够用了
问题
int i=0;
i=i++;
System.out.println("i="+i);//问题:i=?
int j=0;
j=++j;
System.out.println("j="+j);//问题:j=?
大家可以自己试着运行一下,这里公布答案:
i=0
j=1
问题答案解析
需要事先知道的知识
局部变量表:可以理解为真正存放变量值的地方.操作变量时需要把表中变量读到操作数栈中操作
操作数栈:是进行运算的地方.可想而知,操作数栈中操作的变量最后要刷新到局部变量表中
先说问题答案解析后的结论
i++是把i的值放到操作数栈中运算,然后局部变量表中值+1,
++i是把i先在局部变量表中+1,再把加了的新i值放到操作数栈中去运算
结论是如何得到的
这里我拿到了代码对应编译后的字节码文件
对于int i=0; i=i++;
//初始化阶段int i=0
iconst_0 // 将常量0压入操作数栈(栈顶=0)
istore_1 // 将栈顶的0存入局部变量表位置1(i=0)
// 执行 i=i++
iload_1 // 重点是这里,i++是在改变局部变量表数据之前值0加载到操作数栈(栈顶=0)
iinc 1, 1 // 直接在局部变量表中将i自增1(i=1)
istore_1 // 将操作数栈顶的旧值0存回i(覆盖自增结果,i=0)
重点看这两行代码注释:
iload_1 // 重点是这里,i++是在改变局部变量表数据之前值0加载到操作数栈(栈顶=0)
iinc 1, 1 // 直接在局部变量表中将i自增1(i=1)
i最后等于0也容易知道原因了**,因为操作树栈中的结果是i=0,最后操作完成后刷新到局部变量表的新结果i=0会覆盖旧的i自增后的i=1**
对于int j=0; j=++j;
// 初始化阶段
iconst_0 // 将常量0压入操作数栈(栈顶=0)
istore_2 // 将栈顶的0存入局部变量表位置2(j=0)
// 执行 j=++j
iinc 2, 1 // 直接在局部变量表中将j自增1(j=1)
iload_2 // 重点在这里,++j是局部变量表+1之后将值1加载到操作数栈(栈顶=1)
istore_2 // 将栈顶的1存回j(j=1)
重点:
iinc 2, 1 // 直接在局部变量表中将j自增1(j=1)
iload_2 // 重点在这里,++j是局部变量表+1之后将值1加载到操作数栈(栈顶=1)
这里也明白了为什么最后j=1,因为操作数栈中操作的结果是j=1,最后刷新到局部变量表的也是j=1
再来总结一下结论
可以明白了,其实i++和++i在字节码这个层面的区别很简单,就两行字节码指令顺序不一样而已.
所以我总结了一下更深入的口诀
i++:先放到操作数栈操作,再在局部变量表中自增
++i:现在局部变量表中自增,再放到操作数栈中操作