起因是一个群友提出的问题,问以下Java代码的输出的结果是什么?
int i = 1; int j = ((++i) + (++i)); System.out.println(j);
众所周知,单个的++i
赋值是先计算+1然后计算,单个的i++
服之是先赋值后+1计算,但,多个操作复合起来就少有人知了。
接下来我们来研究一下。
经过测试,易得,结果是5。那么这个结果是怎么得到的呢?
首先我们将这段代码反编译一下,可得字节码如下:
// access flags 0x9 public static main([Ljava/lang/String;)V // parameter args L0 LINENUMBER 5 L0 ICONST_1 ISTORE 1 L1 LINENUMBER 6 L1 IINC 1 1 ILOAD 1 IINC 1 1 ILOAD 1 IADD ISTORE 2 L2 LINENUMBER 7 L2 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ILOAD 2 INVOKEVIRTUAL java/io/PrintStream.println (I)V L3 LINENUMBER 12 L3 RETURN L4 LOCALVARIABLE args [Ljava/lang/String; L0 L4 0 LOCALVARIABLE i I L1 L4 1 LOCALVARIABLE j I L2 L4 2 MAXSTACK = 2 MAXLOCALS = 3
先看这一段字节码:
L0 LINENUMBER 5 L0 ICONST_1 ISTORE 1
可以知道,变量i的指针是1,初始值为1
ICONST 是指使用了int的几个常量(<=5)的指针,同理还有LCONST对应long,DCONST对应double。
注意:这里的
_1
中的1,是指针,指向了常量。注意:非常量数值的数据压入操作会有所不同。
ISTORE 是将操作数栈顶上的int数值赋予本地变量,同理还有LSTORE,DSTORE等。
注意:ISTORE参数为指针
再来看来看这一段字节码:
L1 LINENUMBER 6 L1 IINC 1 1 ILOAD 1 IINC 1 1 ILOAD 1 IADD ISTORE 2
首先将变量进行了IINC
操作,给变量+1,其次使用ILOAD
操作读取变量数值(当前为2),加入到操作数栈中。然后下面重复这个操作(当前为3)。最后调用了IADD
进行了加法操作,将操作数栈中的两个数值2+3的结果赋予变量2(就是代码中的j变量)。
最后输出结果5。
IINC
不影响操作数栈,但是会改对应变量的值,所以不需要重新使用ISTORE
压入。
同理我们再来测试i++,代码如下:
int i = 1; int k = ((i++) + (i++) + (i++)); System.out.println(k);
字节码如下:
// access flags 0x9 public static main([Ljava/lang/String;)V // parameter args L0 LINENUMBER 9 L0 ICONST_1 ISTORE 1 L1 LINENUMBER 10 L1 ILOAD 1 IINC 1 1 ILOAD 1 IINC 1 1 IADD ILOAD 1 IINC 1 1 IADD ISTORE 2 L2 LINENUMBER 11 L2 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ILOAD 2 INVOKEVIRTUAL java/io/PrintStream.println (I)V L3 LINENUMBER 12 L3 RETURN L4 LOCALVARIABLE args [Ljava/lang/String; L0 L4 0 LOCALVARIABLE i I L1 L4 1 LOCALVARIABLE k I L2 L4 2 MAXSTACK = 2 MAXLOCALS = 3
注意这一段字节码:
L1 LINENUMBER 10 L1 ILOAD 1 IINC 1 1 ILOAD 1 IINC 1 1 IADD ILOAD 1 IINC 1 1 IADD ISTORE 2
可以看到,这里是先使用ILOAD
操作读取数据到操作数栈中,然后再使用IINC
进行自增,这里就体现了i++
和++i
的区别。
至此,我们已经彻底了解了i++
和++i
。
但是,强烈不推荐这种写法,这种代码难以理解和维护。
参考文档
[1] javase11 jvm doc
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律