当前位置: 首页 > news >正文

Java ++i 与 i++ 底层原理

一、概念解释

1.1 指令含义

  • ICONST_x :将常量x压到操作数栈中
  • ISTORE_x :将操作数栈顶元素写入到本地变量表第x+1位置
  • IINC m n :将本地变量表中第m+1位置进行加n操作
  • LINENUMBER :这个就是标注我们的行号
  • ILOAD_x :将局部变量表第x+1位置元素加入操作数栈中,和ISTORE相反

1.2 局部变量表

  • 是一个数组,用于存储方法中所有的局部变量,包括:
    • 方法参数
    • 方法内部定义的局部变量(int、Object、boolean 等)
    • 编译器临时变量(如:中间值、i++的旧值)
  • 每个变量占用 1 或 2 个槽(slot)
    • int, float, reference → 占1个槽位
    • long, double → 占2个槽位
示例:
public int add(int a, int b) {int c = a + b;return c;
}

这个方法的局部变量表可能如下:

槽位

内容

0

this(对象引用)

1

a

2

b

3

c

1.3 操作数栈

  • 是一个后进先出(LIFO)栈,用于临时存放操作数、计算中间结果
  • 所有字节码指令操作的“数据”,都要先从局部变量表加载进栈,再在栈中操作
  • 每个方法调用都会创建一个新的栈帧,包含一个新的操作数栈
示例:
int a = 3;
int b = 4;
int c = a + b;

字节码执行过程(假设槽位1=3,槽位2=4):

iload_1       // 操作数栈: 3
iload_2       // 操作数栈: 3, 4
iadd          // 操作数栈: 7
istore_3      // 局部变量槽3 = 7

二、简单示例

public class Test {public static void main(String[] args) {int i = 1;int a = i++; // 后缀递增int b = ++i; // 前缀递增}
}

通过Javap 反编译字节码:

javac Test.java
javap -c Test

输出(关键部分)如下:

0: iconst_1         // 将常量1压入栈
1: istore_1         // i = 12: iload_1          // 将i的值加载进操作数栈(i = 1)
3: iinc 1, 1        // i = i + 1,此时 i = 2
6: istore_2         // 把栈顶旧值(1)赋值给 a
//结果 a = 1,i = 27: iinc 1, 1        // i = i + 1,此时 i = 3
10: iload_1         // 把新值加载进栈(i = 3)
11: istore_3        // b = 3
//结果 b = 3,i = 3

分析区别:

表达式

步骤

字节码行为

结果

a = i++

先取值后自增

iload_1(先把i原值放进操作数栈)

iinc(i加1,此时 i = 2)

istore_2(把栈顶旧值赋值给 a)

a = 1,i = 2

b = ++i

先自增后取值

iinc(i先加1,此时 i = 3)

iload_1(把新值加载进栈)

istore_3(把栈顶值赋给b)

b = 3,i = 3

三、深入示例

示例代码:

public class Test {public static void main(String[] args) {int i = 1;int a = i++ + i++;  // 表达式1int b = i++ + ++i;  // 表达式2System.out.println("a = " + a);System.out.println("b = " + b);}
}

 编译并反编译(javac Test.java + javap -c Test):

 0: iconst_1         // i = 11: istore_12: iload_1          // 把 i=1 压入栈顶 → 用于 i++ 的结果3: iinc 1, 1        // i++:i 变为 26: iload_1          // 把 i=2 压入栈顶 → 第二次 i++7: iinc 1, 1        // i++:i 变为 3
10: iadd             // 1 + 2
11: istore_2         // a = 312: iload_1          // i=3,压栈(用于 i++ 的结果)
13: iinc 1, 1        // i++:i = 4
16: iinc 1, 1        // ++i:i = 5
19: iload_1          // i=5,再压栈
20: iadd             // 3 + 5
21: istore_3         // b = 8

3.1 表达式 1:int a = i++ + i++

初始:i = 1
  1. iload_1 → 把 i 的当前值 1 压入操作数栈(用于加法的左值
  2. iinc 1, 1 → i 自增为 2
  3. iload_1 → 把 i 的当前值 2 压入操作数栈(用于加法的右值
  4. iinc 1, 1 → i 自增为 3
  5. iadd → 1 + 2 = 3
  6. istore_2 → 存入变量 a
最终结果:
  • i = 3
  • a = 3
int a = i++ + i++ 的操作数栈变化示意图:

步骤

i 值

操作数栈

说明

初始

1

iload_1

1

1

压入 i(用于计算)

iinc

2

1

i++

iload_1

2

1, 2

再压入 i(计算)

iinc

3

1, 2

i++

iadd

3

3

1 + 2

istore_2

3

a = 3

3.2 表达式 2:int b = i++ + ++i

此时 i = 3
  1. iload_1 → 压入 i 的当前值 3(用于 i++)
  2. iinc 1, 1 → i++,i 变为 4
  3. iinc 1, 1 → ++i,i 再变为 5
  4. iload_1 → 压入 i 的当前值 5(用于 ++i)
  5. iadd → 3 + 5 = 8
  6. istore_3 → 存入变量 b
最终结果:
  • i = 5
  • b = 8
int b = i++ + ++i 的操作数栈变化示意图:

步骤

i 值

操作数栈

说明

初始

3

iload_1

3

3

i++ 左值

iinc

4

3

i++

iinc

5

3

++i

iload_1

5

3, 5

++i 右值

iadd

5

8

3 + 5

istore_3

5

b = 8

http://www.lryc.cn/news/609042.html

相关文章:

  • 机器翻译入门:定义、发展简史与核心价值
  • [自动化Adapt] 录制引擎
  • MVCC:数据库事务隔离的 “时空魔法”
  • mysql管理
  • 【Linux系统】进程间通信:匿名管道
  • http://localhost:8080/photos/xxx.png的本地图片访问方案
  • 常见的框架漏洞(Thinkphp,spring,Shiro)
  • io_submit系统调用及示例
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-54,(知识点:硬件设计流程)
  • 知识随记-----MySQL 连接池健康检测与 RAII 资源管理技术
  • vulnhub-noob靶机攻略
  • ICT模拟零件测试方法--电位器测试
  • 【QT】常⽤控件详解(二)windowOpacitycursorfontsetToolTipfocusPolicystyleSheet
  • 8.1.3 TiDB集群方案雨Replication原理
  • git用户设置
  • 嵌入式 C 语言入门:多文件编程实践笔记 —— 从文件创建到调用
  • Python Seaborn【数据可视化库】 全面讲解
  • C++ 之 【模拟实现 优先级队列】
  • Java 大视界 -- Java 大数据机器学习模型在金融市场情绪分析与投资决策辅助中的应用(379)
  • 控制建模matlab练习05:比例积分控制-①系统建模
  • 【游戏比赛demo灵感】Scenario No.9(又名:World Agent)
  • 【Python✨】解决 Conda 安装 MoviePy 报错问题
  • 【Linux系统编程】进程信号
  • Rust 同步方式访问 REST API 的完整指南
  • python学智能算法(三十一)|SVM-Slater条件理解
  • Rust:如何开发Windows 动态链接库 DLL
  • 【AI编程工具IDE/CLI/插件专栏】-国外IDE与Cursor能力对比
  • 08.Redis 持久化
  • Pytorch实现一个简单的贝叶斯卷积神经网络模型
  • (一)全栈(react配置/https支持/useState多组件传递/表单提交/React Query/axois封装/Router)