• 为什么for循环中的a=a++,a总是0


    很早之前遇到了一个非常有意思的题目,突然想起来,如下

     
    a = 0;
    for(int i = 0; i < 10; i++) {
        a = a++;
    }
    System.out.println(a); //a = ?
     
    

      

    按理说,a最后等于10,但是IDE的执行结果是0.
    使用javap命令查看字节码命令

    javap -c a.class
    

      

     
     
    得到如下代码

    Compiled from "a.java"
    class a {
      a();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
     
      public static void main(java.lang.String[]);
        Code:
           0: iconst_0
           1: istore_1
           2: iconst_0
           3: istore_2
           4: iload_2
           5: bipush        10
           7: if_icmpge     21
          10: iload_1
          11: iinc          1, 1
          14: istore_1
          15: iinc          2, 1
          18: goto          4
          21: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
          24: iload_1
          25: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
          28: return
    }
     
    

      

     
     
     
    一目了然,不如我们这样看更简单 

     
    class a{
        public void test() {
            int a=0;
            a=a++;//a=0
        }
    }
     
     
    使用javap -c
     
    Compiled from "a.java"
    class a {
      a();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
     
      public void test();
        Code:
           0: iconst_0            //a=0     //将int型的0推送至栈顶
           1: istore_1            //     //将int型的数值存入第二个本地变量
           2: iload_1             //     //将第二个int型本地变量推送至栈顶
           3: iinc          1, 1  //     //++操作  局部变量自增指令
           6: istore_1            //     //将int型的数值存入第二个本地变量
           7: return
    }
     
    

      

     
     
     
     
    <wiz_code_mirror>
     
     
     
     
     
     
     
     
     
    class a{
        public void test() {
            int a=0;
            a=++a;    //a=1
        }
    }
     
     
     
     
    Compiled from "a.java"
    class a {
      a();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
     
      public void test();
        Code:
           0: iconst_0
           1: istore_1
           2: iinc          1, 1
           5: iload_1
           6: istore_1
           7: return
    }
     
     
     
     
    对比code
    a++                                                                                                                      
          0: iconst_0            //a=0    //将int型的0推送至栈顶
          1: istore_1            //    //将int型的数值存入第二个本地变量
          2: iload_1            //    //将第二个int型本地变量推送至栈顶
          3: iinc          1, 1  //    //++操作  局部变量自增指令
          6: istore_1            //    //将int型的数值存入第二个本地变量
          7: return    
     
    ++a              
          0: iconst_0        //a=0    //将int型的0推送至栈顶
          1: istore_1         //    //将int型的数值存入第二个本地变量
          2: iinc          1, 1    //    //++操作  局部变量自增指令
          5: iload_1        //    //将第二个int型本地变量推送至栈顶
          6: istore_1        //    //将int型的数值存入第二个本地变量
          7: return
     
    所有至关重要的异步就是:    iinc(局部变量自增)指令与iload_1指令的先后顺序决定的a的值
     
    1)inconst_0将0推送至栈顶
    2)istore 将int型的数值存入第二个本地变量
    3)iload_1 将第2个本地类型推送至栈顶
    3)iinc    局部变量自增指令(注意是局部变量)
    4)istore_1 将int型的值存入第二个局部变量表中(此时栈中的0将覆盖局部变量表中的1)
     

    所以a=a++之所以结果为0,应为局部变量自增的值被覆盖了


    再简单的补充一下关于Java栈的一些知识

    Java中栈是由栈帧组成,每个栈帧都是线程私有的.

    每个栈帧包含4块内容

    1)局部变量表

            局部变量表用来存储参数局部变量,以slot为单位,除了long和double占2个slot,其余的6个基本类型和reference类型占1个slot

    2)操作栈(操作数栈)

            操作栈成为"基于栈的执行引擎",方法执行中进行算术运算或者是调用其他的方法进行参数传递的时候是通过操作数栈进行的

    3)动态链接

            略

    4)返回地址

            略

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    欢迎关注我的公众号:老张大魔王 >>> 不定时更新哦
  • 相关阅读:
    百度正确的打开姿势
    无法安装或运行此应用程序。该应用程序要求首先在"全局程序集缓存(GAC)"中安装程序集 收藏
    ASP.NET智能提示(一)
    全屏窗体的完整方法(转)
    AutoCompleteExtender轻易实现搜索智能提示 附带一点小讨论
    Winform实现百度搜索框智能提示功能( C# )
    C#(asp.net)仿baidu或google智能匹配搜索下拉框
    vs2008 asp.net ajax控件实现百度,谷歌智能搜索
    js实现搜索框智能提示上下移动效果
    sql server 去重复 转帖的
  • 原文地址:https://www.cnblogs.com/dougest/p/14901947.html
Copyright © 2020-2023  润新知