灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:2258回复:0

用javap反编译命令解释i=i++问题

楼主#
更多 发布于:2012-09-08 09:41

[plain]
看下面的简单程序:i的输出结果是多少?(sun 公司2005年的面试题曾出过一道类似的)
[java]
class Hello{
   public static void main(String arg[]){
        int i=0;
        i=i++;
        System.out.print(i);
}
}
先说结果:输出为0
解释:为了弄清楚此程序在java虚拟机中的运行过程,我们用javap反编译命令对javac编译命令生成的Hello.class文件进行了编译结果如下:
[plain]
class Hello extends java.lang.Object{
Hello();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

我们主要看main函数部分:
首先我们要明白:在java 虚拟机中有两个存储区:一个是暂存区(堆栈),一个是变量区。语句istore_1是将堆栈中的值弹出存入相应的变量区(赋值);语句iload_1是将变量区中的值暂存如堆栈中。因为i++是后加操作,即先完成赋值操作,所以 2: iload_1命令即将变量区的0转存到堆栈中,之后完成3: iinc 1, 1即在变量区完成自加,此时变量区的i值为1,之后经 6: istore_1命令又将堆栈中的值0赋值给了变量区的i之后经print函数输出。所以值为0.
为了对比我们看一下i=++i的情况:
[plain]
public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iinc    1, 1
   5:   iload_1
   6:   istore_1
   7:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  iload_1
   11:  invokevirtual   #3; //Method java/io/PrintStream.print:(I)V
   14:  return

}
可以看出先在变量区自加2: iinc 1, 1,之后在将变量区的i值转存的堆栈,再经6: istore_1将堆栈中的值赋给变量区。所以输出为1.
在给出一个只有i++的:
[plain]
public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iinc    1, 1
   5:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   8:  iload_1
   9:  invokevirtual   #3; //Method java/io/PrintStream.print:(I)V
   12:  return

}


摘自 Android_qhdxuan的专栏


喜欢0 评分0
游客

返回顶部