• i++和++i探秘


    从最开始接触编程,就一直有人告诉我们i++和++i不一样,但是没有告诉我,为什么会不一样。呵呵~~

    今天来了解下为什么会不一样。

    首先,来认识一下本文的核心工具:javap命令

    javap是jdk自带的一个工具,可以反编译,也可以查看java编译器生成的字节码,是分析代码的一个好工具。

    通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。

    javap命令格式:

    javap [ options ] class

    options 选项:

    -l                 输出行和变量的表
    -public         只输出public方法和域
    -protected     只输出public和protected类和成员
    -package     只输出包,public和protected类和成员,这是默认的
    -private       输出所有类和成员
    -s               输出内部类型签名
    -c               输出分解后的代码,例如,类中每一个方法内,包含java字节码的指令,
    -verbose     输出栈大小,方法参数的个数                       
    

     ok,回到正题。先写个HelloWord小程序

    public class Hello {
        public static void main(String args[]){
            int i=2;
            i++;
            int j=1;
            ++j;
        }
    }

    将其编译,编译完成之后,执行如下命令:

    javac Hello.java
    javap -c Hello

    得到如下输出:

    E:\>javap -c Hello
    Compiled from "Hello.java"
    public class Hello extends java.lang.Object{
    public Hello();
      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_2    //把2放到栈顶
       1:   istore_1    //把栈顶的值放到局部变量1中,即i中
       2:   iinc    1, 1    //这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,i此时变成3了

    5: iconst_1 //把1放到栈顶 6: istore_2 //把栈顶的值放到局部变量2中,即j中 7: iinc 2, 1 //把局部变量2,也就是j的值,增加1,这个指令不会导致栈的变化,j变成2了 10: return }

    下面在再来看看这个程序:

    public class Hello {
        public static void main(String args[]){
            int i=2;
            i=i++;
            int j=1;
            j=++j;
        }
    }

    再来看看这个反编译的结果:

    E:\>javap -c Hello
    Compiled from "Hello.java"
    public class Hello extends java.lang.Object{
    public Hello();
      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_2  //把2放到栈顶(栈顶=2)
       1:   istore_1  //把栈顶的值放到局部变量1中,即i中(i=2,栈顶=2)
       2:   iload_1   //把局部变量1的值,即2放到栈顶,也就是说此时栈顶的值是2(i=2,栈顶=2)
       3:   iinc    1, 1  //这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,i此时变成3了(i=3,栈顶=2)
       6:   istore_1  //把栈顶的值放到局部变量1中,即i中,栈顶的值是2! (i=2,栈顶=2)

    7: iconst_1 //把1放到栈顶(栈顶=1) 8: istore_2 //把栈顶的值放到局部变量2中,即j中(j=1,栈顶=1) 9: iinc 2, 1 //把局部变量2,也就是j,增加1,这个指令不会导致栈的变化,j此时变成2了(j=2,栈顶=1) 12: iload_2 //把局部变量2的值,即2放到栈顶(j=2,栈顶=2) 13: istore_2 //将栈顶值放到局部变量2中,即j中,所以j=2了(j=2,栈顶=2) 14: return }
  • 相关阅读:
    eclipse luna maven失效的原因
    利用线性探测法解决hash冲突
    PHP和JavaScript将字符串转换为数字string2int
    JavaScript 编程易错点整理
    使用phpstudy创建本地虚拟主机
    单例模式
    PHP使用cookie时遇到的坑
    Redis安装与配置
    CI框架2.x的验证码中所遇问题解决
    用delete和trancate删除表记录的区别
  • 原文地址:https://www.cnblogs.com/yejg1212/p/2946558.html
Copyright © 2020-2023  润新知