i++和++i探秘
从最开始接触编程,就一直有人告诉我们i++和++i不一样,但是没有告诉我,为什么会不一样。呵呵~~
今天来了解下为什么会不一样。
首先,来认识一下本文的核心工具:javap命令
javap是jdk自带的一个工具,可以反编译,也可以查看java编译器生成的字节码,是分析代码的一个好工具。
通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。
javap命令格式:
javap [ options ] class
options 选项:
-l 输出行和变量的表 - public 只输出 public 方法和域 - protected 只输出 public 和 protected 类和成员 -package 只输出包, public 和 protected 类和成员,这是默认的 - private 输出所有类和成员 -s 输出内部类型签名 -c 输出分解后的代码,例如,类中每一个方法内,包含java字节码的指令, -verbose 输出栈大小,方法参数的个数 |
ok,回到正题。先写个HelloWord小程序
public class Hello { public static void main(String args[]){ int i=2; i++; int j=1; ++j; } }
将其编译,编译完成之后,执行如下命令:
javac Hello.java
javap -c Hello
得到如下输出:
E:\>javap -c Hello Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: iconst_2 //把2放到栈顶 1: istore_1 //把栈顶的值放到局部变量1中,即i中 2: iinc 1, 1 //这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,i此时变成3了
5: iconst_1 //把1放到栈顶 6: istore_2 //把栈顶的值放到局部变量2中,即j中 7: iinc 2, 1 //把局部变量2,也就是j的值,增加1,这个指令不会导致栈的变化,j变成2了 10: return }
下面在再来看看这个程序:
public class Hello { public static void main(String args[]){ int i=2; i=i++; int j=1; j=++j; } }
再来看看这个反编译的结果:
E:\>javap -c Hello Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: iconst_2 //把2放到栈顶(栈顶=2) 1: istore_1 //把栈顶的值放到局部变量1中,即i中(i=2,栈顶=2) 2: iload_1 //把局部变量1的值,即2放到栈顶,也就是说此时栈顶的值是2(i=2,栈顶=2) 3: iinc 1, 1 //这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,i此时变成3了(i=3,栈顶=2) 6: istore_1 //把栈顶的值放到局部变量1中,即i中,栈顶的值是2! (i=2,栈顶=2)
7: iconst_1 //把1放到栈顶(栈顶=1) 8: istore_2 //把栈顶的值放到局部变量2中,即j中(j=1,栈顶=1) 9: iinc 2, 1 //把局部变量2,也就是j,增加1,这个指令不会导致栈的变化,j此时变成2了(j=2,栈顶=1) 12: iload_2 //把局部变量2的值,即2放到栈顶(j=2,栈顶=2) 13: istore_2 //将栈顶值放到局部变量2中,即j中,所以j=2了(j=2,栈顶=2) 14: return }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端