zoukankan      html  css  js  c++  java
  • 从字节码层次看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,都是为了自增。

      ~~本文结束,感谢各位看官。

      

  • 相关阅读:
    RabbitMQ介绍
    idea根据Ctrl和滑轮改变字体大小
    com.fasterxml.jackson.databind.exc.InvalidDefinitionException
    Git出现Push rejected: Push to origin/master was rejected
    java单机操作redis3.2.10和集群操作增删改查
    java操作hbase1.3.1的增删改查
    Gobblin采集kafka数据
    使用连接池和缓存机制,处理连接数据库操作
    用cmd导入oracle的.dmp文件和修改oracle管理员密码
    oracle to_date函数和mysql DATE_FORMAT函数用法
  • 原文地址:https://www.cnblogs.com/alinainai/p/11879076.html
Copyright © 2011-2022 走看看