关于的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. Unity代码混淆

    https://www.zhihu.com/question/25414422 http://blog.csdn.net/kun1234567/article/details/7917847 http ...

  2. springboot AOP实战

    目录 AOP实战 maven依赖 定义切面 采用扫描类的方式 采用注解的方式 通知 前置通知 后置通知 返回通知 异常通知 环绕通知 JoinPoint 获取切点处的注解 git AOP实战 mave ...

  3. mysql创建事务,分批次刷新大数据

    对于需要刷新的大数据量,当一次刷新数据量过大时,事务太大,会导致binLog文件太大,在不同的数据库同步时,可能遇到问题,先整理如下,分批次刷新数据 DELIMITER // # 设置//为结束符,否 ...

  4. rpc中的注册中心

    使用模板模式,对注册中心进行设计,可以方便后续添加注册中心 模板抽象类,提供注册中心必要的方法. public abstract class ServiceRegistry { //这是一个模板的抽象 ...

  5. linux常用命令及配置文件

    linux常用命令 基于centos 以我自己实际使用情况来说,从最常用的开始开始,大致如下: 1. 基本命令 cd ls ll(ls -l 别名 ) cat vi/vim touch echo mk ...

  6. C++——自然数求和

    代码如下: #include <iostream> using namespace std; int main() { int a,sum=; for(int i=;i<=;i++) ...

  7. Dubbo系列之 (六)服务订阅(3)

    辅助链接 Dubbo系列之 (一)SPI扩展 Dubbo系列之 (二)Registry注册中心-注册(1) Dubbo系列之 (三)Registry注册中心-注册(2) Dubbo系列之 (四)服务订 ...

  8. agumaster增加了网易数据源

  9. Tomcat源码分析(下载、启动)

    1.下载Tomcat源代码: https://tomcat.apache.org/download-80.cgi 2. 解压以及创建必要目录和配置 解压.新建catalina-home目录,同时将目录 ...

  10. RabbitMQ和Kafka的高可用集群原理

    前言 小伙伴们,通过前边文章的阅读,相信大家已经对RocketMQ的基本原理有了一个比较深入的了解,那么大家对当前比较常用的RabbitMQ和Kafka是不是也有兴趣了解一些呢,了解的多一些也不是坏事 ...