从i++, ++i理解局部变量表和操作数栈

看一个面试题:

public static void main(String[] args) {
		int i = 1;
		i = i++;
		int j = i++;
		int k = i + ++i * i++;
		System.out.println("i=" + i);
		System.out.println("j=" + j);
		System.out.println("k=" + k);
}
运行结果:i=4,j=1,k=11

首先先看简单的模式:
int i = 1;
System.out.println(i++)
int i = 1;
System.out.println(++i)
答案分别为 1,2。
我们拆开来看 i++ 的题,主要是为了后面好解释点。
int i = 1;
System.out.println(i++);
这两行代码的部分汇编指令如下,注意,只列出了几个重点的汇编语句:
ICONST_1 //把常量 1 加载到栈顶
ISTORE 1 //把栈顶的元素弹出,并赋值给局部变量表中位置为“1”的变量,此时指变量i。这两句就相当于 int i = 1;
//接下来执行第二行代码
ILOAD 1 //把局部变量表中位置为“1”的变量加载到栈顶,即把i的值加载到栈顶
IINC 1 1 //直接把局部变量表中位置为“1”的变量加1,即把 i 加1。注意,这条指令并没有修改操作数栈就把 i 加1了。
INVOKEVIRTUAL java/io/PrintStream.println (I)V //把栈顶的元素打印出来,此时栈顶的元素是 1。所以打印的是 1

刚开始时的局部变量表和操作数栈如图所示:
在这里插入图片描述
注意这里是操作数栈,是栈就可以存多个数。
1、执行 ICONST_1,常量 1 进栈

在这里插入图片描述
2、 执行 ISTORE 1,栈顶元素出栈存到位置“1”
在这里插入图片描述
总结,int i =1;在底层汇编就是分为两步。体会局部变量表和操作数栈的区别。接下来的3和4步是i++的操作:
3、 执行 ILOAD 1,把位置“1”的变量值存到栈顶:

在这里插入图片描述
4、 执行 IINC 1 1 ,直接把局部变量表中位置为“1”的变量加 1:
在这里插入图片描述
5、执行 INVOKEVIRTUAL java/io/PrintStream.println (I)V ,把栈顶的元素打印出来,此时栈顶的元素是 1
在这里插入图片描述
总结记录:
1、int i=1 ;分两步:第一步,操作数栈中放1,第二部赋值操作,把操作数栈中的1赋值给局部变量表中的位置1的变量i,同时操作数栈中的1消除
2、i++;也分两步,第一步,先把局部变量表中i的值取出放入操作数栈中的栈顶,第二步,把局部变量表中的i为1的值自增1,变成2,这需要记住。也就是自增、自减操作都是直接修改变量的值,不经过操作数栈。
3、打印的是把操作数栈顶元素取出来然后打印。

回到面试题:

  1. 第一行代码:int i = 1;

在这里插入图片描述
注意,这是两步结果之后的图;

2. 第二行代码:i = i++;
这里有三个步骤,按照前面总结,i++的结果是先取i=1放入操作数栈顶,然后局部变量表自增1,此时操作数栈和局部变量表如图:
在这里插入图片描述
然后第三步是赋值操作,把操作数栈的栈顶元素1,赋值给位置1的变量i。此时操作数栈和局部变量表如图:
在这里插入图片描述

3. 第三行代码:int j = i++;
同样有三步骤:第一步i++的结果是先取i=1放入操作数栈顶,第二步局部变量表自增1,此时操作数栈和局部变量表如图:
在这里插入图片描述
第三步是赋值操作,把操作数栈的栈顶元素1,赋值给位置2的变量j。此时操作数栈和局部变量表如图:
在这里插入图片描述

4. 第四行代码:int k = i + ++i * i++;
可以看成int k = i + (++i)* (i++);
虽然是加了括号,但是也不是括号先算。因为=右边的从左到右加载值依次压入操作数栈。
第一步:取i压入操作数栈:
在这里插入图片描述
++i包含两步,即第二步,先局部变量i自增一,第三步:再把局部变量i压入操作数栈顶在这里插入图片描述
i++也包括两步:第四步,先把局部变量i压入操作数栈顶,第五步,局部变量i自增一:
在这里插入图片描述
第六步进行乘法运算,第七步进行加法运算:
在这里插入图片描述

第八步赋值给局部变量表k:
在这里插入图片描述
至此分析大体结束,最后总结如下:
1、int i=1 ;分两步:第一步,操作数栈中放1,第二部赋值操作,把操作数栈中的1赋值给局部变量表中的位置1的变量i,同时操作数栈中的1消除
2、i++;也分两步,第一步,先把局部变量表中i的值取出放入操作数栈中的栈顶,第二步,把局部变量表中的i为1的值自增1,变成2,这需要记住。也就是自增、自减操作都是直接修改变量的值,不经过操作数栈。
3、=右边的从左到右加载值依次压入操作数栈
4、操作数栈是栈,可以存多个临时结果。
5、打印的是取局部变量到操作数栈,然后把栈顶元素取出来再打印。

参考:http://blog.itpub.net/31561266/viewspace-2222093/

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值