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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 易杰 中级黑马   /  2013-4-15 10:14  /  1418 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 易杰 于 2013-4-17 09:18 编辑

short s1=1; s1=s1+1;这段代码有什么问题没

5 个回复

倒序浏览
有问题啊。
s1+1 这里是short加上int。s1就会升级为int。
所以s1+1 就变成了int。
而 s1 = s1 +1 ( short = int )这样就编译过不去了。  
如果改成  s1 += 1;  这样的话 , 就不会出现问题了,jvm自动帮你处理好了。
以后推荐用  值 += 值  这种写法。

评分

参与人数 1技术分 +1 收起 理由
田磊阳 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 HM刘俊 于 2013-4-15 10:37 编辑

当然有错误,short占2个字节,int占4个字节,short型变量+上int型值计算结果是int型,占4个字节,然后付给一个short型变量s1,就要丢失2个字节的精度,这是不容许的。你非要这么做的话,我给你提供一个办法:
   s1=s1+1;改成s1+=1;虽然是一个意思,但是在jvm里面是不同的方法做的,是运算符重载,所以是不一样的。
《我搜到的答案》
意思就是会丢失精度!
回复 使用道具 举报

short s1=1;
s1(这里的s1属于short类型)=s1(这里的s1被隐式转换为int类型)+1;表达式左边为short类型右边为int类型,两边的类型不一样

评分

参与人数 1技术分 +2 收起 理由
黄玉昆 + 2

查看全部评分

回复 使用道具 举报


short s1=1;s1=s1+1;有什么错?short s1=1;s1+=1;有什么错?
当使用+=、-=、*=、/=、%=、运算符对基本类型进行运算时,遵循如下规则:
• 运算符右边的数值将首先被强制转换成与运算符左边数值相同的类型,然后再执行运算,
且运算结果与运算符左边数值类型相同。
在s1=s1+1;中,s1+1
运算的结果是int型,把它赋值给一个 short型变量s1,所以会报错;而在s1+=1;中,由于
是s1是short类型的,所以1首先被强制转换为short型,然后再参与运算,并且结果也是
short类型的,因此不会报错。那么,s1=1+1;为什么不报错呢?这是因为1+1是个编译时可
以确定的常量,“+”运算在编译时就被执行了,而不是在程序执行的时候,这个语句的效果
等同于s1=2,所以不会报错。前面讲过了,对基本类型执行强制类型转换可能得出错误的
结果,因此在使用+=、 -=、*=、/=、%=等运算符时,要多加注意。


short s1 = 1; s1 = s1 + 1; (s1+1运算结果是int型,需要强制转换类型)
short s1 = 1; s1 += 1;(可以正确编译)

自己亲手在Eclipse敲了一下,答案确实是对的。但是为什么两者功能相同,但是编译器却不同对待呢?
没办法,只有查看下字节码的指令了。
首先是 测试 short s1 = 1; s1 += 1;
字节码:
  1.   public void test();
  2.     flags: ACC_PUBLIC
  3.     Code:
  4.       stack=2, locals=2, args_size=1
  5.          0: iconst_1
  6.          1: istore_1
  7.          2: iload_1
  8.          3: iconst_1
  9.          4: iadd
  10.          5: i2s
  11.          6: istore_1
  12.          7: return
  13.       LineNumberTable:
  14.         line 8: 0
  15.         line 9: 2
  16.         line 10: 7
复制代码
请注意偏移量为5的那个操作码: i2s (即int to short)。
说明编译器在编译时自动添加了i2s操作码。而对于s1 = s1 + 1这种情况,由于没有自动添加 i2s 指令,所以必须显式进行类型转换。

除了short类型外,char和byte同样适用于以上情况。

另外需要注意一点的是对于char,byte,short基本类型的数据,在入栈之前都会被进行带符号化扩展(扩展到一个字长)。因此在操作数栈中不可能存在char,byte和short类型的数据。因为它们都被转换成int类型了。
下面在扩展几个基本知识。
int,long,float,double之间可以相互进行转换。比如int转换成long,相应的指令为i2l,数一数可以知道一共有12种指令。
int转换成char,byte,short的指令为i2c,i2b,i2s,首先会进行相应的截短处理,然后在带符号扩展压栈。
char,byte,short到int 的转换则没有相应的指令,理由很简单,因为它们本来就会被转换成int类型压栈。所以在代码中无需显示强制类型转换。
对于long,float,double转换成char,byte,short,没有相应的指令集。实现中是通过中转int转换的。比如long转换成byte l2i,i2b。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 再接再厉

查看全部评分

回复 使用道具 举报
如果问题未解决,请继续追问,如果没有问题了,请将帖子分类 改为“已解决”,谢谢
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马