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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 了无尘 于 2012-5-14 20:56 编辑

                x = 5;
                System.out.println((x++)+1);
                System.out.println(x);

请问为什么x不是7,这个真是送分的。。。。如果你的回答是表达式完成之后,x才自增,那么看下边
第一题:答案
首先(x++)+1中的小括号毫无意义,小括号并不会改变++运算的优先级,对表达式自增运算符加括号绝大部分是因为需要进行代码的格式化,并告诉java++应该是如何被解释的,否则x+++x只会有一种解释方式。但要注意是否该自增变量的后一表达式元素是否为常量。如都为变量+++就存在2种情况。
其次,这一题里x+++1,也只能进行x++ + 1 这种分割,++1是不行的,常量无法自增。


                x = 5;
                System.out.println(x+++x++);
请问,为什么是11,不是10?
第二题:答案
这一题否定了一部分人所说的自增是表达式运算之后进行的,而另一个模糊的解释是x参加一次运算之后,看起来好像是对的。
分析表达式,会发现,如果是x参加一次运算,那么这个表达式就成了x+x    x++    syso(x)    x++,所以严格来说,是参与一次不为自己的运算,就好像是第一题一样。
我习惯用另一种方式来理解他,虽然这与实际赋值的顺序不一致,因为压后了,但是它好理解,x++的自增将会出现在下次x取值之前,有人用x++ + ++x来阐述。


好吧,有些人可能没有仔细想过我为什么要这么问,有些答案也很有出入,那么追加一个问题

                x=5;
                System.out.println(x+++1+x++);

请问为什么是12,++ 很多人都一知半解,第一题到第三题花了我点心思,希望你们能真的认真思考过,而不是照搬答案,那没有意义,如果你没有仔细查看第一到第三的变化,你会丢失一些知识,呵呵
第三题:答案
这一题将前两题综合了一下,表达式为 x+1   ++x  (5+1)+6  x++


                x=5;
                System.out.println(x+++x);

第四题很有意思,请问为什么是11,我对于你们的小括号很蛋疼,这个怎么加括号,呵呵,开个小玩笑
第四题:答案
这题我说的有意思是指,(x++) + x 和 x + (++x)虽然执行顺序上完全不一致,但是很神奇的是他们结果是一致的,原因不在多说。


以上4次能说明一些东西,但也还缺少一部分
                x=5;
                System.out.println(x++ + 1);
                System.out.println(x++ + x);

第五题,对比以上两行,为什么++的执行顺序完全不一致
第五题:答案
对于前4题,基本该说的,该看的,都差不多了,这里的第三题之所以我加了空格,这很好理解,因为x+++x并不会被java理解成x +  ++x。
而这个题也解释了我上边说为什么参与一次运算是错的,细想一下就可以明白。
x++ + 1被解释成x+1 x++
x++ + x被解释成 x++  x+x   这里为什么是这样呢,因为+x之前,x已经是6了


而这个问题可以使用
        x = 5;
        y = x;
        System.out.println(x+++y);

这样会发现结果为10,也就是说,x++ + y

后记:
自增和自减在实际应用是经常用到的,而在复杂的表达式中,你仍然需要用小括号合理解释到底是先加还是后加。

我的答案可以用来理解,但细微上解释跟字节码执行并不相同,如果想仔细了解,可以javap -c <class文件名>来查看字节码得到正规的执行顺序

如果本帖能让你学到一些东西,那么,恭喜^_^

点评

希望以后你能多发点这种帖子,对大家的学习很有帮助~  发表于 2012-5-14 22:54

评分

参与人数 4技术分 +2 黑马币 +61 收起 理由
kevindavid + 30 赞一个!
李斌 + 1 8楼和9楼的理解哪一个才是正确的啊 好晕哦~.
贠(yun)靖 + 1 + 30
职业规划-刘倩老师 + 1

查看全部评分

32 个回复

正序浏览
 夜风 发表于 2012-5-14 22:50
金钱数目有什么用?还有,我注册的时候没用真实姓名,如果更改?

可以改的    去  黑马程序员常见问题咨询专区
回复 使用道具 举报
自增是表达式运算之后进行的
我认为没有错呀。。。。

System.out.println((x++)+1);这个答案很显然是6,因为在+1的时候x还是5,这个结束以后x才是6

System.out.println(x+++x++);这个答案是11,第一个x是5,第二个x是6,因为第一个x已经++完成了,所以是5+6=11,结束以后x就是7了

System.out.println(x+++1+x++);这个答案是12,还是,第一个x是5,第二个x是6,同理5+1+6=12,结束以后x也是7

System.out.println(x+++x);这个答案是11,同理,第一个x是5,第二个x是6,5+6=11;只不过结束的时候x还是6,

不知道我这样理解是不是错误的,如果错了请批评我,我学习!!!
回复 使用道具 举报
关于第五题的答案我不是很明白哦
x=5;
                System.out.println(x++ + 1);
                System.out.println(x++ + x);
x++ + 1被解释成x+1 x++
x++ + x被解释成 x++  x+x

既然 x++ +x 被解释成 x先自增 然后再求和 那么应该是6+6啊 可是打印结果为11

点评

我之所这么写,x++时,x已经被取值了,也就是第一个x,第二个x是第一个x+1的值,其实怎么写看自己,能理解就行  发表于 2012-5-20 12:32
回复 使用道具 举报
杨志 发表于 2012-5-18 08:46
我的说法就是这样的呢!虽然变量自加,但是只是自加。而栈顶的元素是没有任何影响的。只有当元素被加载到 ...

弹栈这个东西说实话,单拿出来说很多人很难理解,呵呵
回复 使用道具 举报
了无尘 发表于 2012-5-17 23:06
你的说法也不完全对,为什么呢,因为栈顶为x时,虽然是先自加,但是并没有给栈底的那个数赋值,简单来说 ...

我的说法就是这样的呢!虽然变量自加,但是只是自加。而栈顶的元素是没有任何影响的。只有当元素被加载到栈顶中时。栈顶的元素才会变化!嘿嘿!
回复 使用道具 举报
杨志 发表于 2012-5-17 22:57
我的理解或者说我的判断的结果是根据汇编的运行顺序。
这里的x++ 和++x只是压入栈区的顺序不一样。
x++, ...

你的说法也不完全对,为什么呢,因为栈顶为x时,虽然是先自加,但是并没有给栈底的那个数赋值,简单来说就是为什么有些人会说是值被重置了。这个说的有点难理解,我说不太清楚

换个说法,如果真的是先自增,但x在加法运算上并没有改变值,问题出现在哪里?问题应该出现在iinc指令上
回复 使用道具 举报
了无尘 发表于 2012-5-17 04:02
谁说的对,或者好,并不重要,重要的是你学到东西,你的理解是什么?任何事情都要保持好奇心,尽管你觉得 ...

我的理解或者说我的判断的结果是根据汇编的运行顺序。
这里的x++ 和++x只是压入栈区的顺序不一样。
x++,会先将数据压入栈顶,然后在将变量自加。
这样栈顶的元素就不变。
++x,会先进行自加,再去压入栈顶。
这样就导致了为什么会出现一个会加1 而另一个没有加1.
至于栈区这些就是数据结构的知识了。
而当需要数据的时候用又将变量压入栈区。这就是为什么 x++ +x++;
中的第二个x的值会等于x+1.

还有就是你的这句代码:
  1. System.out.println(x++ + 1);
复制代码
你的这句代码:你说会被解释成: x+1 x++;
但是我认为会是x先自加1,再去和1相加。
因为根据反汇编过来的代码看出:
  1. 0:   bipush  6
  2. 2:   istore_1
  3. 3:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
  4. 6:   iload_1
  5. 7:   iinc    1, 1
  6. 10:  iconst_1
  7. 11:  iadd
  8. 12:  invokevirtual   #3; //Method java/io/PrintStream.println:(I)V
  9. 15:  return
复制代码
这里的add方法是最后执行的。
本人认为当弄懂了这些个底层的东西。这些所谓的++x和x++。
还有那些个莫名其妙的题目都是浮云吧!之所以现在出这么多的问题。
就是大家都只是存在理解上面。根本没有去知道计算机真正底层是怎么去实现的。
个人意见。谢谢!
回复 使用道具 举报
杨志 发表于 2012-5-16 14:37
你的答案很多我不怎么好理解!但是我根据javap -c的字节正规执行,都能得到正确答案! ...

谁说的对,或者好,并不重要,重要的是你学到东西,你的理解是什么?任何事情都要保持好奇心,尽管你觉得某人说的对,或者不对,你都要自己去证明谁是对。
回复 使用道具 举报
你的答案很多我不怎么好理解!但是我根据javap -c的字节正规执行,都能得到正确答案!
回复 使用道具 举报
我在想,是不是学编译原理会对这样的题有体会啊。
回复 使用道具 举报
李斌 发表于 2012-5-15 22:33
9楼解释的更清楚 受教了。。。

学到东西就好
回复 使用道具 举报
9楼解释的更清楚 受教了。。。{:soso_e179:}
回复 使用道具 举报
马浩 发表于 2012-5-13 12:12
x = 5;
                System.out.println((x++)+1);//x在完成运算后才自增
               System.o ...

还是你解释得比较清楚:victory:
回复 使用道具 举报
本帖最后由 龚正军 于 2012-5-15 18:32 编辑
孙峰 发表于 2012-5-15 13:40
请问9楼的第二题里,“ 相当于:x+(++x++);  ”那我这么写程序就提示错误啊



其实我在上面已经在最后讲解过这问题了我说了++x+++x是指向错误!!!
这个错误是由于前面说了:我再用一个例子解释下这个问题的发生 ,避免其他同学也遇到这问题:

如在:++x++时候,java判定前两个++x已经累加了X一次,但是后面两个++就“不是”X++了(你的误会就产生在这),他会认为X是+(加)上了一个“+”(此+号算字符所代替的ASCII代码数字)java不允许+去加一个“+”这个非int,所以提示了错误(上面最后我已经提示过这问题的发生了)。
而你吧X+++X++加括号成:x+(++x++),那么括号里面就具备了优先级,所以相当于++x++,JAVA是不允许你加一个加号的。--------所以报错!(我上面就是用这个错误来证明第3个+是JAVA优先识别成加号的)

PS:我9楼的回答是我凌晨学习的时候弄的,当时很累了,论坛回答的那个排版不熟,郁闷我半天,修改N次,弄了我快2小时,所以很多字打错啊,还有解释得很模糊啊,请大家多谅解啊,抱歉,抱歉!!)
回复 使用道具 举报
呵呵!却是学好好多东西!!9楼的得自己去研究下!!
回复 使用道具 举报
孙峰 黑马帝 2012-5-15 13:40:05
18#
请问9楼的第二题里,“ 相当于:x+(++x++);  ”那我这么写程序就提示错误啊

QQ截图20120515133455.png (5.56 KB, 下载次数: 66)

QQ截图20120515133455.png
回复 使用道具 举报
第一题答案,对于(x++)+1,是先运算x+1后,在将x自增,然后重新赋值给x。即(x++)+1=6,x=6.
第二题答案,x+++x++,可以理解成x+(++x++),就可以理解为5+(6++)小括号内的x自增,然后将x与x++的和再自增后重新赋值给x,即该运算结束后,表达式结果为11,但x=12.
追加题这时候根据第一题第二题就可以理解为x+(++(1+x)++),即先运行x+1=6,然后就变为x+(++y++),此时y=6,这时候同第二题。
第四题就理解为x+(++x),即5+6=11.
第五题应该是计算机不认识++1的过程,所以转换成(x+1)++,同理x++ +x可以表示为(x++) +x,即先自增,在求和。
有错指出请指教。


回复 使用道具 举报
顶一下楼主,太给力了!
回复 使用道具 举报

回帖奖励 +10

金钱数目有什么用?还有,我注册的时候没用真实姓名,如果更改?
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马