前言
如果只用一般的常识解释i++和++i的话
- i++ 先将i赋值再++
- ++i 先++再赋值
然而这简略的答复并不能入吸引面试官的眼球,如果用java字节码指令剖析则成果齐全不同。
代码实现
public class OperandStackTest {/** 程序员面试过程中, 常见的i++和++i 的区别 */ public static void add(){ //第1类问题: int i1 = 10; i1++; System.out.println(i1);//11 int i2 = 10; ++i2; System.out.println(i2);//11 //第2类问题: int i3 = 10; int i4 = i3++; System.out.println(i3);//11 System.out.println(i4);//10 int i5 = 10; int i6 = ++i5; System.out.println(i5);//11 System.out.println(i6);//11 //第3类问题: int i7 = 10; i7 = i7++; System.out.println(i7);//10 int i8 = 10; i8 = ++i8; System.out.println(i8);//11 //第4类问题: int i9 = 10; int i10 = i9++ + ++i9;//10+12 System.out.println(i9);//12 System.out.println(i10);//22 } public static void main(String[] args) { add(); }}
运行后果
字节码指令
通过javap -v out
目录下的class文件名 在终端运行失去如下后果
public static void add(); descriptor: ()V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=10, args_size=0 0: bipush 10 2: istore_0 3: iinc 0, 1 6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 9: iload_0 10: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 13: bipush 10 15: istore_1 16: iinc 1, 1 19: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 22: iload_1 23: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 26: bipush 10 28: istore_2 29: iload_2 30: iinc 2, 1 33: istore_3 34: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 37: iload_2 38: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 41: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 44: iload_3 45: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 48: bipush 10 50: istore 4 52: iinc 4, 1 55: iload 4 57: istore 5 59: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 62: iload 4 64: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 67: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 70: iload 5 72: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 75: bipush 10 77: istore 6 79: iload 6 81: iinc 6, 1 84: istore 6 86: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 89: iload 6 91: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 94: bipush 10 96: istore 7 98: iinc 7, 1 101: iload 7 103: istore 7 105: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 108: iload 7 110: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 113: bipush 10 115: istore 8 117: iload 8 119: iinc 8, 1 122: iinc 8, 1 125: iload 8 127: iadd 128: istore 9 130: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 133: iload 8 135: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 138: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 141: iload 9 143: invokevirtual #5 // Method java/io/PrintStream.println:(I)V 146: return
解释以上运行后果
第一类问题
对应的指令为
先将i1的值为10入栈(bipush),而后将int类型的值从栈中存到局部变量表0的地位,而后执行iinc将0地位的值+1,而后将局部变量表0地位的数入栈执行输入操作
所以i1的值为11
先将i2的值为10入栈(bipush),而后将int类型的值从栈中存到局部变量表1的地位,而后执行iinc将1地位的值+1,而后将局部变量表1地位的数入栈执行输入操作
所以i2的值为11
总结
因为没有赋值操作,区别不大。
第二类问题
先将i3入栈存储到局部变量表2的地位,而后将它入栈,执行iinc将2地位的值加一,i4存储到部分表量表3的地位
所以i3是11,i4还是10
将i5入栈存储到局部变量表4的地位,因为是++i所以先iinc将4地位的值加一,而后将局部变量表4的值入栈,执行赋值操作,所以都是11
第三类问题
先将i7入栈,而后存到局部变量表6的地位,先把i6入栈,而后把6处的值加一,因为又将这个值存储到局部变量表6处,所以产生笼罩又把值变为10。
而++i不会产生笼罩先执行加一而后再把值入栈,在赋值给局部变量表中,所以i8为11。
第四类问题
先将i9=10入栈,而后存在局部变量表8的地位
int i10 = i9++ + ++i9;
先iload将8地位的i9入栈而后执行iinc将8处的i9加一,而后执行++i9,在将8处的i9加一
此时i9=10+1+1为12,而后将8地位的i9入栈,执行add将栈中的两i9相加,失去的值存储到局部变量表9的地位
所以i10=10+12(i9++后还是10,++i9后是12,因为执行了两次iinc操作)
而后调用虚办法和静态方法,在将9处的值入栈执行输入语句
原文链接:https://blog.csdn.net/demo_yo...
版权申明:本文为CSDN博主「石破天惊代码人」的原创文章,遵循CC 4.0 BY-SA版权协定,转载请附上原文出处链接及本申明。
近期热文举荐:
1.1,000+ 道 Java面试题及答案整顿(2021最新版)
2.别在再满屏的 if/ else 了,试试策略模式,真香!!
3.卧槽!Java 中的 xx ≠ null 是什么新语法?
4.Spring Boot 2.5 重磅公布,光明模式太炸了!
5.《Java开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞+转发哦!