A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

原题是这样的
public class Test {
    public static void main(String[] args) {
        int i = 1;
        i = i++;
        System.out.println(i);
    }
}
求输出?

大家先别看下面的解释,也别运行程序,自己想想想结果,如果你的结果跟我一样 输出了2,那么就请看看下面这段高手的解释:注:我是直接复制的,不是我的,方正我看了后逐渐懂了,我觉得人家讲的比我说更清楚,就借用下了:关于作者,确实找不到出处了,因为我找的地方也是人家标注,复制的

i=0;i=i++为什么等于0这个问题困扰了我好长的一段时间,结果前段时间还试图从虚拟机那个层面进行解释,但无论是线程还是方法调用都不能解释其现象,发现方向性错误,这只是一个语言的特性而已。在java lang spec中提到:
1、java运算符的优先级++符是大于=的。
2、The result of the postfix increment expression is not a variable, but a value.后++符表达式的结果是个值而不是一个变量。
也就是说后++符先将自己的值存储起来,然后对变量进行++;
再进行赋值操作,也就是将先存储起来的值赋给变量i,这样的操作就导致了i值被置为0了


对于C和C++来说不一样,在讲到m=i++操作时,C语言是先将i的值赋给了m,然后将i值++,这样i=i++的结果自然就是1了,c的实现中是不存在那个中间的值的存储的。


由于java和c不同的语言特性,导致了i=i++的不同之处,前面的笔记中已经提到,由于java lang spec中的一些细微规定,导致其运行结果的不同,我们可以用个例子来看i=i++在jvm中实际的运行过程。
源程序test.java:
public class test {
  public test() {
  }
  public static void main(String[] args) {
    int i=0;
    i=i++;
  }

}
我们用javap来看其实际的虚拟机指令集:
C:\JBuilderX\jdk1.4\bin>javap -c  -classpath "d:/" test
Compiled from "test.java"
public class test extends java.lang.Object{
public test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   nop
   5:   return

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0 //常数0入栈
   1:   istore_1 //i赋值,常数值出栈
//至此完成i=0;
   2:   iload_1  //装载变量i,0入栈
//第2步是特殊的一步,这步将i值先行保存,以备赋值使用
   3:   iinc    1, 1 //变量值增加,栈内值不变
//至此完成i++
   6:   istore_1 //i赋值,0出栈。
//至此完成i=i++
   7:   nop  //donothing
   8:   return

}

对比而言,对于i++而言,i=i++指令多了两步,2和6
其实这两步是赋值符号引起的,有意思的是第二步出现的时机,是在iinc之前,这就是因为java lang spec中规定的。

4 个回复

倒序浏览
1 ++符号在后面先进行其他运算再自加运算 自加运算完成时程序也就是结束的时候
回复 使用道具 举报
第一个程序结果就是1啊,这个i=i ++;是先赋值再自增,而这个i++自增后并没有保存,不知道你是不是表达这个意思。。
回复 使用道具 举报
这个看见很多次了,楼主的解析太长,没耐心看。。。。。其实主要是i在自增之前,系统另外开辟了一个内存空间把i自增前的值存起来,然后进行自增操作,最后进行赋值操作,把新内存里的i的原值赋给了自增后的i,所以最终i的值不变。i=i--也是一样
回复 使用道具 举报
楼主,你解释都不是你发的原题, int i = 1;
        i = i++;输出就是1啊
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马