【Java基础】i = i + 1,i += 1, i++, ++i 的区别

本文探讨了Java中i = i + 1, i++, ++i的区别,包括它们在编译和运行时的行为。通过分析局部变量表和操作数栈,揭示了i++是先使用后增加,而++i是先增加后使用的原理,并通过实例代码展示了它们在表达式中的具体影响。" 125034500,5589275,ASM字节码操作:删除已有类的Instruction与NOP,"['java', 'jvm', '字节码操作']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题引入:

最开始是因为看到了一个题:

short s1 = 1; s1 = s1 + 1;
short s1 = 1; s1 += 1;

上面两条是否都可以成功编译?

答:① 中,由于 1 是 int 类型的,因此 s1 + 1 也是 int 类型的,需要进行强制类型转换,才能赋值给 short;
② 中,s1 += 1 就相当于 s1 = ((short)s1 + 1)+= 本身就隐含着强制类型转换,故可正确编译。

问题拓展:

上面涉及到了 +=s1 = s1 + 1 的区别,除了 += 本身隐含强制类型转换以外,+= 的效率也会比 s1 = s1 + 1 高一些。

突然想起了多次看过的 i++++i 的区别的问题,当时只是大概知道 i++ 是用完了再自增,而 ++i 是自增了再用,既然想到了,就从原理上搞搞清楚。

一个 Test 看 i++ 和 ++i:

查资料的过程中看到了一个题,自己去跑了一下:

package test;

public class test {

	public static void main(String[] args) {
		int i = 1;
		i = i++;
		System.out.println("i=" + i);
		int j = i++;
		System.out.println("j=" + j + " i=" + i);
		int k = i + ++i * i++;
		System.out.println("k=" + k + " i=" + i);
	}
}

输出结果:
在这里插入图片描述

原理分析:

从《深入理解Java虚拟机(第3版)》里可以看到,每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。

而这里会用到的是栈帧中的局部变量表、操作数栈

对于 i++ 来说,一共需要 2 步:
① 把 i 放到操作数栈里;
② 对局部变量表里的 i 自增。

对于 ++i 来说,与上面相反:
① 对局部变量表里的 i 自增,此时操作数栈为空;
② 把 i 放到操作数栈里。

下面来看 test 里的每个语句对应着发生了什么,首先需要明确:

System.out.println 输出的是局部变量表里的值;
操作数栈,是一个后入先出栈。当一个方法刚刚开始执行的时候,该方法的操作数栈是空的,在方法执行的过程中,会有个各种字节码指令望操作数栈中写入和提取内容,也就是出栈和入栈操作。赋值操作是将操作数栈中的操作数经过运算后赋值给局部变量表中的变量的。

int i = 1; 此时局部变量表中为 i = 1 ,操作数栈为空

i = i++; 注意不是 i++,是先 i++ 然后有个赋值操作:
① i 进操作数栈,此时局部变量表 i = 1 ,操作数栈 i = 1
② 局部变量表中自增,此时局部变量表 i = 2,操作数栈 i = 1
③ 赋值操作是将操作数栈中的数赋值给 i ,此时局部变量表 i = 1,操作数栈 i = 1

int j = i++; 跟上面的操作类似,只是最终赋值给了 j :
① ②与上面的相同;
③ 将中的 i = 1 赋值给局部变量表中的 j,此时局部变量表 i = 2,j = i(1),操作数栈 i = 1

int k = i + ++i * i++; 这条语句包含了四个部分,分别是 ii++++i,以及最后计算完的赋值操作:

(1) int k = i + ++i * i++;
i 入栈,此时局部变量表 i = 2 ,操作数栈 i = 2;

(2) int k = i + ++i * i++;
①局部变量表中自增,此时局部变量表 i = 3 ,操作数栈 i = 2;
② i 入栈,此时局部变量表 i = 3 ,操作数栈 i = 3, i = 2;

(3) int k = i + ++i * i++;
① i 入栈,此时局部变量表 i = 3 ,操作数栈 i = 3,i = 3, i = 2;
② 局部变量表中自增 1,此时局部变量表 i = 4,操作数栈 i = 3,i = 3, i = 2;

(4) 赋值给 k
对操作数栈中的操作数进行运算,再赋值给局部变量表中的 k,即 k = 3 * 3 + 2 = 11。

参考资料:

  1. 《深入理解Java虚拟机(第3版)》
  2. 公众号文章:终于弄明白 i = i++和 i = ++i 的区别了!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值