• 用字节码解释i++,++i


    首先看代码

    public static void main(String[] args) {
            int i = 0;
            i = i++;
            System.out.println(i);
        }

    打印结果是0,而如果是i=++i,那么打印将会1。下面我们从字节码的角度来分析为什么是这样。

    在讲字节码之前,先简单的了解下Java栈,在JVM中有这么一个数据结构叫Java栈,当线程启动的时候,会分配一块内存当做该线程的栈,每个栈由一系列的栈帧组成。每个栈帧对应一个方法,当线程执行方法时,就是栈帧出栈入栈的过程。

    每个栈帧包含三部分数据:本地变量(参数+方法内的变量)、操作数栈和其它数据,本文主要涉及本地变量和操作数栈。

    先看后置i++的实现

    public static void main(String[] args) {
            int i = 0;
            i = i++;
        }

    编译之后的字节码如下:

    整个过程这样的:

     可以发现变量在执行命令iinc 1,1的时候已经变成1了,但是istore_1又把变量所在位置覆盖成了0,所以执行完i = i++,i还是原来那个值。

    下面,来看下前置++的实现:

    字节码就不再解释了,整个过程实现如下:

    和后置++不同的地方在于,在变量进入操作数栈之前,就先执行了iinc指令,所以进入操作数的值是加1后的值,最后写回的值也是最新值。

    给出今天用到的字节码的含义

    Bytecode

    Stack

    before->after

    Description

    iconst_0

    ->0

    Loads the int value 0 onto the stack

    istore_1

    value->

    Store int value into variable 1

    istore_2

    value->

    Store int value into variable 2

    iinc

    No change

    Increment local variable #index by signed byte const

    iload_1

    ->value

    Loads an int value from variable 1

    iadd

    value 1,value 2->result

    Adds 2 ints together

    说明两点需要注意的地方:

    ①iinc此操作对应于自加操作,并且该操作不对stack有任何改变;

    ②iadd操作过后只在stack中保留结果result。

    原文链接:https://mp.weixin.qq.com/s/Vmf5uPmZrloPkbASSy3M8w

  • 相关阅读:
    spring+hibernate常见异常集合
    Java报错原因汇总
    java常见异常集锦
    连接池 druid(阿里巴巴的框架)
    企业支付宝账号开发接口实现
    Maven使用常见问题整理
    MySQL的分页
    Struts2中通配符的使用
    Centos下安装mysql 总结
    将linux用在开发环境中
  • 原文地址:https://www.cnblogs.com/qingchen521/p/8579844.html
Copyright © 2020-2023  润新知