• java中i = i++问题


    今天偶然呗问到了一个java中自增运算符的问题,涉及到了堆栈,觉得挺有趣的把它记录下来。

    int i=0;
          i=i++;
          结果i是多少?
          这是一个经常被提及的问题,答案一直五花八门。
          具体测试一下以说明问题:
          代码1:

    1. public class Test{
    2.     public static void main(String[] args){
    3.          int i=0;
    4.          i=i++;
    5.          System.out.println(i);
    6.     }
    7. }

         结果i依然是0.分析其反编译后的代码:
        

    1. public static void main(java.lang.String[]);
    2.   Code:
    3.    0:   iconst_0     //0放到栈顶
    4.    1:   istore_1    //把栈顶的值保存到局部变量1,也就是i中
    5.    2:   iload_1     //把i的值放到栈顶,也就是说此时栈顶的值是0
    6.    3:   iinc    1, 1  //注意这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,也就是说局部变量1,即i此时为1了。
    7.    6:   istore_1     //把栈顶的值(0)保存到局部变量1,也就是让i为0了,所以最后i为0
    8.    7:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
    9.    10:  iload_1
    10.    11:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
    11.    14:  return

    值得注意到是i被修改了两次,第一次是i++;i变为1,最后一次是i=0;所以结果i是0
    代码2:

    1. public class Test2{
    2.     public static void main(String[] args){
    3.          int i=0;
    4.          int j=0;
    5.          j=i++;
    6.          System.out.println(i);
    7.          System.out.println(j);
    8.     }
    9. }

    这个结果肯定都知道,i是1,j是0.同样看反编译之后的代码:

    1. public static void main(java.lang.String[]);
    2.   Code:
    3.    0:   iconst_0
    4.    1:   istore_1     //i=0
    5.    2:   iconst_0
    6.    3:   istore_2     //j=0
    7.    4:   iload_1      //把i的值放到栈顶,也就是说此时栈顶的值是0
    8.    5:   iinc    1, 1  //局部变量1加1,也就是让i++了,此时i已经是1了,上面说过,此指令不会导致栈变化
    9.    8:   istore_2     //把栈顶的值(注意是0)存入局部变量2,也就是j中,所以j=0
    10.    9:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
    11.    12:  iload_1
    12.    13:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
    13.    16:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
    14.    19:  iload_2
    15.    20:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
    16.    23:  return

    很明显可以看出,java是先把i的值取出来放到栈顶,我们可以认为是引入了第三个变量int k=i;然后i++,这时候i为1了,然后让j=k;也就是0.结论,i的++运算是在对j这个变量的赋值之前完成的。

    代码3:

    1. public class Test3{
    2.     public static void main(String[] args){
    3.          int i=0;
    4.          int j=0;
    5.          j=++i;
    6.          System.out.println(i);
    7.          System.out.println(j);
    8.     }
    9. }

    结果大家也都知道,i=1,j=1
    看操作过程:

    1. public static void main(java.lang.String[]);
    2.   Code:
    3.    0:   iconst_0   
    4.    1:   istore_1    //i=0
    5.    2:   iconst_0
    6.    3:   istore_2     //j=0
    7.    4:   iinc    1, 1   //局部变量i加1,这时候i变成1了 。
    8.    7:   iload_1     //把i的值放到栈顶,栈顶的值是1
    9.    8:   istore_2    //j=1
    10.    9:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
    11.    12:  iload_1
    12.    13:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
    13.    16:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
    14.    19:  iload_2
    15.    20:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
    16.    23:  return

    对比代码2和代码3,关键的差别就是iload_1   个iinc这两条指令的位置变了。

  • 相关阅读:
    liunx上升级python2至python3
    python之logging日志
    c# 脚本引擎 脚本编辑器
    设置 BCompare 打开文件时的默认字符编码
    Python调用动态库,获取BSTR字符串
    服务器CPU100%的排查日志
    栈(Stack)
    搭建个人的github.io博客
    django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17)
    virtualenv中使用python的虚拟环境
  • 原文地址:https://www.cnblogs.com/zzcc/p/5000124.html
Copyright © 2020-2023  润新知