前言

如果只用一般的常识解释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开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!