黑马程序员技术交流社区

标题: 简单的For循环,仔细看为何呢!!! [打印本页]

作者: lionel    时间: 2015-1-11 00:45
标题: 简单的For循环,仔细看为何呢!!!
public class test {
        public static void main(String[] args) {
                int j = 0;
                for(int i = 0; i < 10; i++){
                        j = j++;
                }
                System.out.println("j = " + j);
        }
}
作者: lgn187    时间: 2015-1-11 04:36
j++自增变成了1,然后又被0赋值,变回了0,这个过程循环十次,j还是0
作者: xinjian00    时间: 2015-1-11 08:50
很简单,你把 j = j++;  j = ++j;   j++;  ++j这几个式子搞明白就好了
作者: 446111220    时间: 2015-1-11 09:40
楼上说的对,J应该先自增再赋值,而不是先赋值再自增,不然肯定是一直为0.
作者: luke_yang    时间: 2015-1-11 09:41
j = j++;用老是一句话就是  先出去玩了,在回家吃饭。先用,在加。
作者: 邓士林    时间: 2015-1-11 10:11
说说这题我的理解吧!第一眼看的时候,我也懵了,然后自己研究了一个小时,谈不上,也是上网找资料,还没整理好,拿出来说说吧!勿喷
1、先看C#中的执行,C#公共运行环境CLR与Java的JVM差不多,确实如此:
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int j = 0;
            for(int i=0;i<10;i++)
            {
                j=j++;
            }
            System.Console.WriteLine("j = " + j);
        }
    }
}
运行结果也是0;
2、C语言运行:(看图片吧!)论坛为什么图片不能插入到具体的位置,纠结,大家就看图片吧!
3、Java运行(看图片)
4、调试Java时的现象(看图片)
为什么结果出人意料,我们看下C#帮助文档MSDN(ps:其实它有个论坛,现在CSDN八成就是模仿他)
MSDM中的一句言简意赅话:
第一种形式是前缀增量操作。该操作的结果是操作数加 1 之后的值。
第二种形式是后缀增量操作。该运算的结果是操作数增加之前的值。
那么我们理解这题,就可以这样说,j = j++;执行的本质,是将j自加前的值赋值给j,所以一直0;ps:执行顺序是++运算符优先于=赋值运算符,貌似可以解释通。
找了半天,看到有人找到JVM的解释:
jvm里面有两个存储区,一个是暂存区(是一个堆栈,以下称为堆栈),另一个是变量区。
语句istore_1是将堆栈中的值弹出存入相应的变量区(赋值);语句iload_1是将变量区中的值暂存如堆栈中。
因为i = i++;是先将i的值(1)存入堆栈,然后对变量区中的i自加1,这时i的值的确是2,但是随后的istore_1又将堆栈的值(1)弹出赋给变量区的i,所以最后i =1
注意:istore_1iload_1是反编译的语言,看不懂!你要是懂汇编和反汇编应该知道吧!反正我不懂。
我理解的:(我觉得能解释通)
java的编译器在遇到i++和i--的时候会重新为变量运算分配一块内存空间,以存放原始的值,而在完成了赋值运算之后,将这块内存释放掉。先将i的原始值存放在变量区,然后i++,此时栈中的i确实为1,执行赋值的时候,是把变量区中的值(原始值)赋值到栈中,所以又为0
c/c++中没有另外设置一个临时变量或是临时空间来保存i,所有操作都是在一个内存空间中完成的。所以会出现结果为10
下面附一张解释图(别人的)。不知道大家看懂没有,不懂就多看看,或找资料,因为我看一个小时,才得出我的理解,如上红字

C#.png (9.87 KB, 下载次数: 67)

C#运行

C#运行

c.png (7.77 KB, 下载次数: 120)

C语言运行

C语言运行

java.png (10.26 KB, 下载次数: 132)

Java运行

Java运行

java测试.png (76.51 KB, 下载次数: 123)

Java测试运行

Java测试运行

梵蒂冈.jpg (85.82 KB, 下载次数: 79)

解释图

解释图

作者: 以利亚    时间: 2015-1-11 10:44
j是先赋值然后在自增的,但j自增后并没有赋值,所以j还是0,因此结果一直为0
作者: 史磊    时间: 2015-1-11 19:39
这个比较简单啊 只要把++ --搞清楚 先后的问题
作者: 自信流云    时间: 2015-1-11 20:48
学习了
作者: 466273082    时间: 2015-1-11 21:03
解释好多呀,能简单点吗
作者: jinghoujiayin    时间: 2015-1-11 22:36
多看看视频,这种问题很容易的
作者: zhengyijun    时间: 2015-1-11 23:24
这个我还真愣了,试了下结果确实是0。我的理解是:j++是先参与运算再自增,这样的话那就是先j=j-->j++(相当于j=j+1)。那j岂不是变1了吗?可是结果确实是0。求解释啊。感谢楼主啊,以前一直不知道,上网搜搜看。
作者: 时间来过    时间: 2015-1-12 09:48

++在操作数的前面时,先进行自增运算,再进行其他运算。
++在操作数的后面时,先进行其他运算,在进行自增运算。
j=j++是先赋值,j=0然后,j才自增。此时参与运算的j值为运算后也就是赋值后的j。j++的自增并没有赋值给j,所以,j的值一直为0,并没有记录其自增的值。

作者: 周景新    时间: 2015-1-12 10:59
学习了。。。。
作者: xiaoyi    时间: 2015-1-12 11:48
xinjian00 发表于 2015-1-11 08:50
很简单,你把 j = j++;  j = ++j;   j++;  ++j这几个式子搞明白就好了

这个做实验自己一下子就明白了
作者: 209920266    时间: 2015-1-12 11:49
绕太多容易混。我是这么理解的:
j=0;
<1>j=j++;可以看成:j=0    0++,先赋值。后运算。
<2>j=++j;可以看成:0++  j=1,先运算,后赋值。
作者: 小敏儿    时间: 2015-1-12 12:17
j是先赋值再自增,但是自增后没有在赋值,相当于自增后的结果没有保存,所以一直是0
作者: 李增宽    时间: 2015-1-12 21:40
i++ 和++i的区别
作者: iblackhorse    时间: 2015-1-12 22:07
结果是0,我们已经在群里讨论过了。比较有意思
作者: IcedCoffee    时间: 2015-1-12 22:10
是群里的吧 顶一下 阿门 多看看有助于学习
作者: 奔跑的猴子    时间: 2015-1-27 10:37
本帖最后由 奔跑的猴子 于 2015-1-27 10:40 编辑

勿喷,刚刚测试,结果又变成0了,好好想想再回答




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2