i++

      在初次学习i++++i时我们就一直牢记着:i++是先使用后加1,++i是先加1再使用,长时间都一直这样搬着砖(这结论当然是没毛病的),我也是。直到我看见了下面的题目。

public static void func(){
    int i=0;
    for(int j=0;j < 100;j++){
        i = i++;
    }
    Stystem.out.println(i);//打印什么???
}

      我是觉得打印100的,毫无疑问,我错了。
      看来我还是太菜了,看看字节码吧!

 0 iconst_0
 1 istore_0
 2 iconst_0
 3 istore_1
 4 iload_1
 5 bipush 100
 7 if_icmpge 21 (+14)

10 iload_0
11 iinc 0,1
14 istore_0

15 iinc 1,1
18 goto 4 (-14)
21 getstatic #2 <java/lang/System.out>
24 iload_0
25 invokevirtual #3 <java/io/PrintStream.println>
28 return

      其中10~14对应的就是i=i++的字节码。强烈建议给IDEA安装上Jclasslib插件,这样能更方便的指定助记符的含义。

  • iload_0: 将当前栈帧的局部变量数组的索引为0的局部变量的值推送到操作数堆栈上。
  • iinc 0,1: 将索引为0的局部变量按1递增。
  • istore_0: 将值从操作数堆栈中弹出(记为val),并且将索引为0的局部变量值设置为val。

      看完这三个助记符我们就会发现iinc虽然讲值递增了,但是没有设置给i,所以i的值一直没有变,i++完全没有任何作用。动图如下:

字节码操作流程

      嗯,就这样,i被改变后又被栈上的值给覆盖了~_~

++i

      现在我们换一下题,换成++i

public static void func(){
    int i=0;
    for(int j=0;j < 100;j++){
        i = ++i;
    }
    Stystem.out.println(i);//打印什么???
}

      对应字节码如下。

 0 iconst_0
 1 istore_0
 2 iconst_0
 3 istore_1
 4 iload_1
 5 bipush 100
 7 if_icmpge 21 (+14)

10 iinc 0,1
13 iload_0
14 istore_0

15 iinc 1,1
18 goto 4 (-14)
21 getstatic #2 <java/lang/System.out>
24 iload_0
25 invokevirtual #3 <java/io/PrintStream.println>

      依旧是不变的10~14行,
请输入图片描述

      如此i就可以被改变了,打印100。

混合操作

      在i++++i的笔试题中经常混合使用,一堆+号头疼。如:i= (i++)+(i++)+(++i)+(++i);。咱先来个简单的(如i = i++ + ++i;),否则字节码都迷糊了。其实这个的答案很简单,只是我们需要通过它的字节码更理解而已。字节码如下。

 0 iconst_0
 1 istore_0

 2 iload_0
 3 iinc 0,1
 6 iinc 0,1
 9 iload_0
10 iadd
11 istore_0

12 getstatic #2 <java/lang/System.out>
15 iload_0
16 invokevirtual #3 <java/io/PrintStream.println>
19 return

      我们只需要关注2~11行,这几步对应的值和栈如下图所示。画图这也是本文的目的所在。

请输入图片描述

困难模式

      来,画它i= (i++)+(i++)+(++i)+(++i);,看看看官能否画出过程图呢^_^。字节码如下。

 0 iconst_0
 1 istore_0

 2 iload_0
 3 iinc 0,1
 6 iload_0
 7 iinc 0,1
10 iadd
11 iinc 0,1
14 iload_0
15 iadd
16 iinc 0,1
19 iload_0
20 iadd
21 istore_0

22 getstatic #2 <java/lang/System.out>
25 iload_0
26 invokevirtual #3 <java/io/PrintStream.println>
29 return

      我们只需要关注2~21行。

点我查看过程图

请输入图片描述

Last modification:May 16th, 2020 at 12:59 am
如果觉得我的文章对你有用,请随意赞赏