• 为什么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)返回地址

            略

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    欢迎关注我的公众号:老张大魔王 >>> 不定时更新哦
  • 相关阅读:
    《网络攻防实践》6.0
    《网络攻防实践》5.0
    Docker 本地镜像发布到阿里云(完结篇)
    Vue 实战-9 Vue公共js功能函数的封装和使用
    Vue 实战-8 单独运行测试.js文件
    Docker 常用安装
    DockerFile 解析及案例
    Docker 容器数据卷
    Docker 镜像原理
    多字段模糊匹配 -->搜索功能(mysql原生语句实现)
  • 原文地址:https://www.cnblogs.com/dougest/p/14901947.html
Copyright © 2020-2023  润新知