从字节码来说明i++与++i到底有什么不同
看字节码之前需要先了解相关概念,如栈帧、操作数栈、局部变量表。
栈帧是JVM中很重要的一个概念,因为JVM是基于栈的架构。一个方法的调用其实就是栈帧入栈出栈的过程。栈顶栈帧就是当前方法调用。
一个栈帧中包含:
局部变量表存储的是方法的参数以及内部定义的变量的值,操作数栈也是一个栈结构,用来执行方法中的指令。
好了,来看一个代码片段:
1 | class Scratch { |
为了不产生其他多过信息,这里只写了关键代码。
首先可以通过javac
将源码编译成class:
1 | javac scratch.java |
执行完成后将看到Scratch.class 文件,通过javap命令查看字节码:
1 | javap -c Scratch > scratch.txt |
为了方便查看将结果输出到了scratch.txt,打开此文件将看到如下信息:
1 | Compiled from "scratch.java" |
关注main方法 0-5,可以发现对应的是:
1 | int i=0,j=0,m=0; |
主要是声明变量并初始化为0。我们可以发现下划线后面跟了一个数字,这里应该代表的是变量在局部变量表中的位置。
i:1
j:2
m:3
再关注main方法:6、7、10:iload_1
表示将局部变量表中位置1的数据放入操作数栈中(这里对应的是i,此时i的值为0)然后pop出来赋值给j。然后再将i自增iinc
。最后istore_2
存储j到局部变量表中。
操作完成后i=1,j=1。
最后关注main方法:11、14、15:iinc
首先自增i,然后iload_1
将局部变量表中位置1的数据放入操作数栈中(这里对应的是i,此时i的值为2)然后pop出来赋值给m。最后istore_3
存储m到局部变量表中。
操作完成后i=2,j=1,m=2。
这就是为什么大家都说,i++是先赋值后自增,而++i是先自增后赋值的原因。
这里要说明的是,如果是单独的i++、++i是没有什么区别的。
从字节码来说明i++与++i到底有什么不同