从字节码角度分析java中的i++与++i

int j=0;
for(int i=0;i<100;i++)
j=j++;
System.out.println(j);

如果你运行一下上面的程序,就会发现它打印的结果居然是0,但是如果把j=j++换成j++的话就会打印100.这是为什么呢?
如果你稍微有一点经验就会知道i++与++i的区别:
i++是在所有其他操作完成之后,自身加1。
++i是在自身加1之后,再去完成其他操作。
为什么++放在前面和后面区别这么大呢?
让我们从字节码的角度看看是怎么回事儿吧!
首先在这之前我们应该对java的栈有一点了解。
在jvm中有这么一个数据结构叫java栈,当线程启动的时候,会分配一块内存当做该线程的栈,每个栈由一系列的栈帧组成。每个栈帧对应一个方法,当线程执行方法时,就是栈帧出栈,入栈的过程。
每个栈帧包含三部分数据:本地变量(参数+方法内的变量)、操作数栈和其他数据,本文主要涉及本地变量和操作数栈。
这里写图片描述
先看看i++的实现:
public static void main(String[] args){
int i=0;
i=i++;
}

编译之后的字节码如下:

 public static void main(java.lang.String[]);
     flags: ACC_PUBLIC, ACC_STATIC
     Code:
        stack=1,locals=2,args_size=1
             0:iconst_0          //把数值0 push到操作数栈
             1:istore_1          //把操作数栈写回到本地变量第2个位置
             2:iload_1           //把本地变量第2个位置的值push到操作数栈
             3:iinc   1,1        //把本地变量表第2个位置加1
             6:istore_1          //把操作数据栈写回本地变量第2个位置
             7:return
        LineNumberTable:

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

另外,来看下++i的实现:

 public static void main(java.lang.String[]);
     flags: ACC_PUBLIC, ACC_STATIC
     Code:
        stack=1,locals=2,args_size=1
             0:iconst_0          //把数值0 push到操作数栈
             1:istore_1          //把操作数栈写回到本地变量第2个位置
             2:iinc   1,1        //把本地变量表第2个位置加1
             3:iload_1           //把本地变量第2个位置的值push到操作数栈
             6:istore_1          //把操作数据栈写回本地变量第2个位置
             7:return
        LineNumberTable:
             line 16:0
             line 17:2
             line 18:7

整个过程实现如下
这里写图片描述
和i++不同的地方在于,在变量进入操作数栈之前,就先执行了iinc指令,所以进入操作数的值是加1后的值,最后写回的值也是最新值。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值