从字节码层面理解i++和++i
起因
无非就是网上常见的面试题
public static void main(String[] args) {
int i = 0;
int result = i++ + ++i + i++;
System.out.println(i);
System.out.println(result);
}
这种题目怎么理解才对呢?
我以前只知道,i=i++;i=++i;理解的话,通过背口诀,先赋值还是先+1. 但是上述面试题就不知道如何理解了。
当然面试题只是面试题,要是实际开发中有人这么写,头给他打爆。
理解
最近几天在看jvm,这个从编译出来的字节码就能很清晰的看出来为什么。
j=++i 从字节码来看,大概顺序是,innc 1 by 1 ;iload 1;istore_2
j=i++ 从字节码来看,大概顺序是,iload 1;innc 1 by 1 ;istore 2
i=++i 从字节码来看,大概顺序是,innc 1 by 1;iload 1;istore_1;
i=i++ 从字节码来看,大概顺序是,iload 1;innc 1 by 1;istore 1;
这里没有jvm知识的人,可能不太理解,其实jvm中,字节码运行通过俩个地方来不断交换数据来进行运行的。
在jvm中,局部变量表和操作数栈是两个不同的存储数据的内存区域。
innc 1 by 1 意思就是局部变量表数+1;
iload 1 意思是局部变量表1位置节点的数,加载到操作数栈。
istore 1 意思是从局部变量表出栈一个元素,覆盖到局部变量表1位置。
那么我们来理解一下j=++i;
innc 1 by 1 ;iload 1;istore_2
假设i=1;则
局部变量表1位置的数据1加1,则此时局部变量表1的数据为2。
获取局部变量表的1位置数据2,加载到操作数栈,则此时局部变量表1的数据为2,操作数栈数据为2.
操作数栈的数据2出栈,覆盖到局部变量表2的位置上。
那么此时局部变量表1既是i的数据为2,局部变量表2既是j的数据也是2。
同理
j=i++的话。
iload 1;innc 1 by 1 ;istore 2
假设i=1;则
获取局部变量表的1位置数据1,加载到操作数栈,则此时局部变量表1的数据为1,操作数栈数据为1.
局部变量表1位置的数据1加1,则此时局部变量表1的数据为2。
操作数栈的数据1出栈,覆盖到局部变量表2的位置上。
那么此时局部变量表1既是i的数据为2,局部变量表2既是j的数据也是1。
那i=++i的话。
innc 1 by 1;iload 1;istore_1;
假设i=1;则
局部变量表1位置的数据1加1,则此时局部变量表1的数据为2。
获取局部变量表的1位置数据2,加载到操作数栈,则此时局部变量表1的数据为2,操作数栈数据为2.
操作数栈的数据2出栈,覆盖到局部变量表1的位置上。
那么此时局部变量表1既是i的数据为2
那i=i++的话。
iload 1;innc 1 by 1;istore 1;
假设i=1;则
获取局部变量表的1位置数据1,加载到操作数栈,则此时局部变量表1的数据为1,操作数栈数据为1.
局部变量表1位置的数据1加1,则此时局部变量表1的数据为2。
操作数栈的数据1出栈,覆盖到局部变量表1的位置上。
那么此时局部变量表1既是i的数据为1
这几种情况理解后,自然就能清楚的理解上面的面试题,
i=3,result是4