关于的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的更多相关文章

  1. 从字节码层面看“HelloWorld” (转)

    一.HelloWorld 字节码生成 众所周知,Java 程序是在 JVM 上运行的,不过 JVM 运行的其实不是 Java 语言本身,而是 Java 程序编译成的字节码文件.可能一开始 JVM 是为 ...

  2. 从字节码层面看“HelloWorld”

    一.HelloWorld 字节码生成 众所周知,Java 程序是在 JVM 上运行的,不过 JVM 运行的其实不是 Java 语言本身,而是 Java 程序编译成的字节码文件.可能一开始 JVM 是为 ...

  3. 从字节码指令看重写在JVM中的实现

    Java是解释执行的.包含动态链接的特性.都给解析或执行期间提供了非常多灵活扩展的空间.面向对象语言的继承.封装和多态的特性,在JVM中是怎样进行编译.解析,以及通过字节码指令怎样确定方法调用的版本号 ...

  4. 从java字节码角度看线程安全性问题

    先看代码: package com.roocon.thread.t3; public class Sequence { private int value; public int getNext(){ ...

  5. 从jvm字节码指令看i=i++和i=++i的区别

    1. 场景的产生 先来看下下面代码展示的两个场景 @Testvoid testIPP() { int i = 0; for (int j = 0; j < 10; j++) { i = i++; ...

  6. i++ 与 ++i 的从字节码层面看二者的区别

    /** * javap命令可以对class反汇编得到其字节码文件(此命令并不是jdk8开始的,只不过jdk8中对工具进行加强,增加了一些参数,可通过 javap -help了解) * * 注意: * ...

  7. 从JVM字节码执行看重载和重写

    Java 重写(Override)与重载(Overload) 重写(Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变.即外壳不变,核心重写! 重写的 ...

  8. java中i=i++字节码分析

    原文出处: Ticmy 1 2 int i = 0; i = i++; 结果还是0为什么? 程序的执行顺序是这样的:因为++在后面,所以先使用i,"使用"的含义就是i++这个表达式 ...

  9. 《深入理解Java虚拟机》-----第8章 虚拟机字节码执行引擎——Java高级开发必须懂的

    概述 执行引擎是Java虚拟机最核心的组成部分之一.“虚拟机”是一个相对于“物理机”的概念 ,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的,而 ...

随机推荐

  1. sort(桶排序+hash)

    题目链接:https://cn.vjudge.net/problem/HDU-1425 注意是多组输入 代码: #include<cstdio> #include<iostream& ...

  2. springboot2.x基础教程:Swagger详解给你的接口加上文档说明

    相信无论是前端还是后端开发,都或多或少地被接口文档折磨过.前端经常抱怨后端给的接口文档与实际情况不一致.后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新.其实无论是前端调用后端,还是后端调用 ...

  3. 哦!这该死的 C 语言

    前言 C 语言是一门抽象的.面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首 ...

  4. Linux下vim的安装及配置

    目录 一.vim的下载 二.vim的基本知识 三.vim的基本配置 四.vim与外部文件的复制粘贴 一.vim的下载 Ubuntu系统,输入命令: sudo apt install vim Cento ...

  5. jzoj 6798. 【2014广州市选day2】regions

    Description 在平面上堆叠着若干矩形,这些矩形的四边与平面X坐标轴或Y坐标轴平行.下图展示了其中一种情况,3个矩形的边将平面划分成8个区域: 下面展示了另一种稍稍复杂一些的情况: 你的任务是 ...

  6. oracle之二表和表空间的关系

    表和表空间的关系 建一个使用缺省值的表空间SQL> create tablespace a datafile '/u01/data/urpdb/a01.dbf' size 10m; 利用orac ...

  7. loadrunner做http接口的性能测试

    不用录制脚本的方法 步骤: 1.先打开Virtual User Generator——选择Web/HTTP协议,进入到主页面,这里不按照传统录脚本的方式输入url,所以直接叉掉录制脚本选项,进入下面的 ...

  8. python中unittest参数化

    先安装 pip install parameterized 在测试用例类中,@parameterized.parameterized.expand(这里面传一个列表),这个就是参数化的意思

  9. Anaconda是个什么东东?

     2020/5/18 一.Anaconda 有什么用? 是一个安装.管理python相关包的软件,还自带python.Jupyter Notebook.Spyder,有管理包的conda工具,非常有用 ...

  10. Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...