public class test{
public static void main(String[] args){
int i = 0;
for(int j = 0; j < 10; j++){
i = i++;
System.out.println(i);
}
}
}
为什么输出是10个0?
又为什么把i++换作++i又输出1至10呢?

解决方案 »

  1.   

    考虑第一次循环
    i++表达式的值是0
    这时i++运算以后虽然i的值是1
    但是又把i++表达式的值赋给了i
    所以i的值永远都是0
    等于说是把i=1这一步给屏蔽掉了而++i表达式的值是1
    这样i就会一直加1
      

  2.   

    http://community.csdn.net/Expert/topic/3885/3885309.xml?temp=.6516535楼主,看看这个帖子!
      

  3.   

    请zhutouzip(Speak out!-shyboy) 解释一下
    我一直都是这么理解的
      

  4.   

    嗯,这个问题,很复杂,好像怎么说都讲得过去,i=i++的确是i没+1就给了i,但是之后,最终还是要自加的,问题是等号两边是赋值动作谁先完成!
    应该去问问gosling,^^
      

  5.   

    看看这个帖子,会有帮助你理解的
    http://community.csdn.net/Expert/topic/3885/3885309.xml?temp=.9122278
      

  6.   

    ++运算符的优先级高于=,因此首先计算i++;(i++)的结果为0,同时作为表达式的一部分i的值成为1;然后执行=运算符,将(i++)的结果赋值给i;
    因此最后i的值为0
    看完这个就应该明白了。
      

  7.   

    上边说的不对。Sorryjava的编译器搞的鬼!在遇到++和--操作符的时候会重新为原变量分配一块内存空间,以存放原始的值,而在完成了赋值运算之后,就将这块内存释放掉。由于i的原始值存放在后开辟的内存中,这样i=i++后,由于是先赋值,i就会得到i的原始值(存放在新内存中的数椐),而原来内存位置的i自加后只保留在原来的位置,由于此时i指向已经是新开辟出来的内存地址,所以i的值没有发送变化!
    换句话说,
    while(true){
       i=i++;
    }
    永远执行i的值恒等于i的初始值,即使不是0也一样!下面我把过程写一下i=0;//假设此时内存地址为0x12345678
    i=i++;//系统新开内存地址0x99999999,存放i原始值0,然后0x12345678的存放数据+1操作
          //此时0x12345678=1,0x99999999=0,但是上一步是先给值,所以i的内存地址是0x99999999=0;所以i=0,但是,如果是
    i=0;
    i++;
    此时i=1,因为0x99999999处新开辟的内存地址没有给任何引用,所以被丢弃了!i继续使用0x12345678处值
      

  8.   

    恩 我来个小小的总结哈我对上面青蛙的理解如下,不知道正确与否,高人批判了整个过程这样:1 i=0;//这个过程是最初的赋值2 创建新的一个地址空间  存放旧的数据 就是i = 0 先执行++是因为++优先级这里高
      旧的空间变成了i++ 这个时候i=13 赋值 因为++的执行特性 是先把i以前的值赋出去,然后才改变(就是+1)
      所以变成1的i就又被原始数据改回了04抛弃新开辟的空间 则只有原来的空间,i还是0p.s 其实新空间 和原空间的i都是0了吧?
      

  9.   

    我不知道有谁会在程序中这样写 i = i++,++本来就是自增运算符,你还要写 i = i++,想表达什么意思.这除了让人感到困惑外也没有其他的用处了吧.
      

  10.   

    因为i++是先用了i之后在自加1的,所的第一个循环中i=i++之后才加1,也就是i被赋值为0,你不妨改为++i,试试就知道为什么了
      

  11.   

    哇,讲的那么复杂,都讲到编译器里面去了i=i++ 加号在后面的时候,就是先使用i,再加一 
    i=++i 加号在前面的时候,就是先加一 ,再使用i
      

  12.   

    “i=0;
    i=i++;”等式左边的i(以下简称左i,位于栈外)等式右边的i(以下简称右i,位于栈内,是左i被推人栈内的一个副本)在“++”定义上确实是先赋值再自增,即i先被赋为0,然后自增为1。
    但是在jvm实现的时候,却是先自增再赋值:先将右i及其“++”符推入栈中,然后jvm一看到++时知道这是个后++,所以应该先弹栈赋值然后自增,它以为只要不在栈内给右i自增就行了(因为最后赋值是弹栈赋值,栈外的值改变不会影响到栈内值,即不影响最后赋值),于是先去栈外把左i的值自增,但它没想到栈内外是同一个值,这样做的后果是赋值后用右i的值把已自增为1的左i又赋回了0。
    总结:这一问题的出现是由于jvm在遇到“=”时呆板的入栈弹栈操作导致的,弹栈赋值时确实是用了没自增前的值,但是自增操作却自作聪明地先在栈外做了,此时若“=”两边的变量是同一值时(“j=i++”就能够正常工作),弹栈后就导致自增操作白做了。
      

  13.   

    引用别人:>>也就是说在++之前已经返回了计算的值给了等号左边,所以后面的++是在栈里的临时变量进行计算的,这样就不会影响原来的变量值。呵呵,兄台,其实我不是这个意思。你没理解我的意思。
    我是说因为编译器比较规板,把赋值语句i=i++
    生成了i入栈,计算表达式,出栈赋值i的三板斧,
    但是这里计算表达式不是在栈上计算的!
    所以导致一次多余的入栈和弹栈,清除了本来已经计算好的结果你看看iinc的JVM Spec描述
    iinc OperationIncrement local variable by constant
    Format
     iinc   
    index   
    const   
    Operand Stack No change看到了没有,No Change!!!iinc是直接对变量操作的,不是把操作数放到stack计算的,有点特殊是不是?和传统语言不太一样。你在栈上没有计算,正确的过程是你把i的值0放到栈上
    然后把i变成1,但是栈上还是0
    最后把栈上的0弹出来赋值给i,结果把刚才iinc的结果给冲掉了,i又变成了0
      

  14.   

    i的初值0,i++ =执行的顺序是
    取i 的初值0 ,然后把i++变为1但是由于是i++
    所以赋值的时候给的还是i++前的0值,
    所以循环结束后i的值还是0;每次循环都是这样当然最后是10个,0了。