从字节码层次看i++和++i

关于的Java的i++和++i的区别,初学者可能会混淆,这时候有经验的同学或同事就会告诉你,++在后,就会立马加值,
++在后则会等会儿再加,所以如果i == 0 ,那么i++ == 0,++i == 1。
那么这个先加后加具体在字节码中是怎样一个逻辑呢?这个就需要我们去看看Java的字节码了,如何查看字节码请
参考我之前的文章IDEA设置External Tools之Javap反编译字节码。
准备两个函数
函数test1

函数test2

先直接上函数的打印结果就,再来慢慢分析

先看test1的字节码

0~3行:一次定义了i和j两个变量,并赋值为0,存放在局部变量表。
4~7行:开始循环的逻辑,if_icmpge是比较语句,如果j>=50则直接跳到第21行,调用打印方法。
核心的逻辑在10~15行:

现将局部变量表slot 0的变量加载到操作数栈,接着对局部变量表自增(没错,你没看错,这里是对局部
变量表自增而不是对操作数栈的变量自增)。。紧接着下一步istore_0又把栈顶的值存回局部变量表slot_0,所以,。。
最终局部变量表的值是没有改变的。
i++分析完毕,再回看上面的字节码,其中还有值得注意的地方:

21~43行:这段对应代码
1 System.out.println("i++: " + i);
先new一个PrintStream对象,下面可以看到是new了一个StringBuilder对象。这里可能是jvm的一个优化,将字符串拼接
改成了StringBuilder来append,所以我们经常看到的有人说要把字符串拼接改成StringBuilder其实大可不必,先看下字节码
对于语句的优化是怎样的。
接着来看test2方法的字节码:

前面的代码和test1一样,我们直接来看不一样的地方:

该段字节码对应代码:
i = ++i;
先对局部变量表上的值自增,再加到操作数栈,最终存回到局部变量表,这样的话变量表的值就是实实在在
增加了的。
所以,回想上面的分析,得出结论就是:i++是将变量表的值加载操作数栈后再对变量表上的值自增,而++i
则是先对变量表上的值自增后再将其加载到操作数栈。
当然,殊途同归,最终不管是i++还是++i,都是为了自增。
~~本文结束,感谢各位看官。
从字节码层次看i++和++i的更多相关文章
- 从字节码层面看“HelloWorld” (转)
一.HelloWorld 字节码生成 众所周知,Java 程序是在 JVM 上运行的,不过 JVM 运行的其实不是 Java 语言本身,而是 Java 程序编译成的字节码文件.可能一开始 JVM 是为 ...
- 从字节码层面看“HelloWorld”
一.HelloWorld 字节码生成 众所周知,Java 程序是在 JVM 上运行的,不过 JVM 运行的其实不是 Java 语言本身,而是 Java 程序编译成的字节码文件.可能一开始 JVM 是为 ...
- 从字节码指令看重写在JVM中的实现
Java是解释执行的.包含动态链接的特性.都给解析或执行期间提供了非常多灵活扩展的空间.面向对象语言的继承.封装和多态的特性,在JVM中是怎样进行编译.解析,以及通过字节码指令怎样确定方法调用的版本号 ...
- 从java字节码角度看线程安全性问题
先看代码: package com.roocon.thread.t3; public class Sequence { private int value; public int getNext(){ ...
- 从jvm字节码指令看i=i++和i=++i的区别
1. 场景的产生 先来看下下面代码展示的两个场景 @Testvoid testIPP() { int i = 0; for (int j = 0; j < 10; j++) { i = i++; ...
- i++ 与 ++i 的从字节码层面看二者的区别
/** * javap命令可以对class反汇编得到其字节码文件(此命令并不是jdk8开始的,只不过jdk8中对工具进行加强,增加了一些参数,可通过 javap -help了解) * * 注意: * ...
- 从JVM字节码执行看重载和重写
Java 重写(Override)与重载(Overload) 重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变.即外壳不变,核心重写! 重写的 ...
- java中i=i++字节码分析
原文出处: Ticmy 1 2 int i = 0; i = i++; 结果还是0为什么? 程序的执行顺序是这样的:因为++在后面,所以先使用i,"使用"的含义就是i++这个表达式 ...
- 《深入理解Java虚拟机》-----第8章 虚拟机字节码执行引擎——Java高级开发必须懂的
概述 执行引擎是Java虚拟机最核心的组成部分之一.“虚拟机”是一个相对于“物理机”的概念 ,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而 ...
随机推荐
- 15_Python的模块module
1.模块的概述 1.模块是Python程序架构的一个核心概念,每一个以.py结尾的Python源代码文件都是一个模块 2.模块名和标识符的命名规则一样,由数字字母下划线组成且不能以数字开头,也不要和系 ...
- 实验 2:Mininet 实验——拓扑的命令脚本生成
实验 2:Mininet 实验--拓扑的命令脚本生成 一.实验目的 掌握 Mininet 的自定义拓扑生成方法:命令行创建.Python 脚本编写 二.实验任务 通过使用命令行创建.Python 脚本 ...
- GaussDB(DWS)应用实战:对被视图引用的表进行DDL操作
摘要:GaussDB(DWS)是从Postgres演进过来的,像Postgres一样,如果表被视图引用的话,特定场景下,部分DDL操作是不能直接执行的. 背景说明 GaussDB(DWS)是从Post ...
- Linux:用tar解压文件出现错误Not found in archive
问题:用tar解压文件出现错误Not found in archive 解决办法:加上-C参数 tar -zxvf ZenTaoPMS.8.1.3.zbox_64.gz -C /usr 因为压缩文件 ...
- vue父子传值与非父子传值
大概梳理下传值的几种方式 一:父子组件传值 props方式 子组件对外暴露方法并向父组件传递由于触发方法导致的值的变化,父组件接收子组件传递来的值:子组件接收父组件传递来的值,并根据传递来的值在子组件 ...
- Solr专题(一)手把手教你搭建Solr服务
一.Solr是什么,能解决什么问题? Solr是一个高性能,采用Java开发,基于Lucene的全文搜索服务器.同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展并对 ...
- Java I/O流 复制文件速度对比
Java I/O流 复制文件速度对比 首先来说明如何使用Java的IO流实现文件的复制: 第一步肯定是要获取文件 这里使用字节流,一会我们会对视频进行复制(视频为非文本文件,故使用之) FileInp ...
- Java链接db2相关
端口一般是50000或者60000 后面跟的可能是库名(个人猜测) 还有db2jcc.jar安装db2的可以从相应目录下载未安装的可以…(啥时候有空再传上来)
- [程序员代码面试指南]递归和动态规划-换钱的方法数(DP,完全背包)
题目描述 给定arr,arr中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,求组成aim的方法数. 解题思路 完全背包 和"求换钱的 ...
- MySQL隐式转换的坑
MySQL以以下规则描述比较操作如何进行转换: 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做 ...