从字节码指令说清Java自增原理(i++, ++i)

面试时经常碰到这样的面试题

int i = 0;
i = i++;

i输出多少?

int i = 0;
i = ++i;

i输出多少?

网上有很多文章,但是大部分都是模棱两可,甚至自己都说不清,接下来我将从JVM字节码指令的角度来说明

参考来源:《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》

首先,明确几个概念

栈帧

1、Java的方法以栈帧的形式存储在虚拟机栈中;

2、每个方法栈帧包含局部变量表、操作数栈、动态链接、方法出口共四个部分,本文仅涉及到局部变量表、操作数栈两部分;

3、局部变量表以变量槽(slot)的方式存储局部变量(local variable),可以简单理解为数组,举个例子

int a = 10;
int b = 11;

上述代码片段对应的局部变量表如下图所示

4、操作数栈是大部分字节码指令集直接操作的对象,就是普通的栈结构。

自增相关指令集

iconst_<i>

将int型i压入操作数栈

istore_<n>

将操作数栈顶元素退栈,存储在局部变量表slot n处,该指令可以理解为赋值指令,即将操作数栈顶元素赋值给局部变量;

iload_<n>

将局部变量表slot n处的数据压入操作数栈顶

iinc index, const

将slot index处的数据直接加上const,该指令的特别之处在于直接操作局部变量表,不经过操作数栈。

实例分析

示例代码

public class Test1 {
	public static void main(String[] args) throws Exception {
        System.out.println(inc1());
        System.out.println(inc2());
	}

	public static int inc1() {
		int i = 0;
        i = i++;
        return i;
	}
	public static int inc2() {
		int i = 0;
        i = ++i;
        return i;
	}
}

javap查看class文件对应的字节码指令

javap -v Test1

方法inc1()对应的指令如下图

 方法inc2()对应的指令如下图

两图对比,可以发现,i++和++i最大的区别在于iinc和iload两个指令的执行顺序不同,因此造成了inc1()返回值为0,而inc2()返回值为1。 

每行代码对应的指令见下图

public static int inc1() {
		/* iconst_0
		*  istore_1
		*/
		int i = 0;
		/*
		* iload_1
		* iinc 1,1
		* istore_1
		*/
        i = i++;
        return i;
	}
	public static int inc2() {
		/* iconst_0
		*  istore_1
		*/
		int i = 0;
		/*
		* iinc 1,1
		* iload_1
		* istore_1
		*/
        i = ++i;
        return i;
	}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值