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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© mynet 初级黑马   /  2013-11-4 16:08  /  1216 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

short s1 = 1;s1 = s1 + 1;有什么错?short s1 = 1;s1 += 1;有什么错?

评分

参与人数 1黑马币 +1 收起 理由
乔兵 + 1

查看全部评分

3 个回复

倒序浏览
一、以容量角度来解释:
对两个容量不一样的数据类型的变量进行算术运算时,java会自动将小容量的变量进行精度提升,然后再进行运算,得到的结果类型是提升后的大容量的数据类型.如果将该结果赋值给小容量的数据类型的变量,则必须进行强制的类型转换,否则编译程序会报损失精度错.
short s1 = 1;
int i = 1;
首先,因为short类型是16位的,而int类型是32位的,在进行
(s1+i) 运算时,自动将s1提升到32位,然后与i相加,得到的结果是32位的,而此时
s1=s1+i; 必然报错,执行强转:
s1=(short)(s1+i); 就没问题了.
s1+=i;能编译通过并得到正确结果,而 s1=s1+i; 却报错,是因为它们在类型不同时要区别对待,s1+=i的方式java会对i进行窄化转换,由编译程序自动执行.
java规范中说:
E1 op=E2 实际上等价于 : E1=(T)( (E1)op(E2) )
其中T是E1的数据类型.这种类型转换或者是一个恒等转换,或者是一个窄化转换.
这个说明java是一种强类型的语言,对数据类型的要求是非常严格的,否则会引起混乱.
下面解释一下三种类型转换:恒等转换(相同容量的两个数据类型之间的赋值);拓宽转换(小容量类型赋值给大容量类型);窄化转换(大容量赋值给小容量类型). 实际上,前两种转换都是编译程序自动执行的,而窄化转换则要求必须显式的执行.
总结:根据以上解释就可以做出判断了:该题目是大容量赋值给小容量数据类型,即窄化转换,就要进行强制转换,应该这样:short s1 = 1; s1=(short)(s1+i); 所以第一问是错的。java会对s1+=i的方式自动进行窄化转换,不需要强制进行,所以是可以正常编译的。
二、按+=的运算功能来解释
第一种方式:
short s1 = 1; s1 = s1 + 1;需强行转化
因为short s1=1在栈中开辟了一个short类型的空间;
而s1=s1+1;中s1是short类型,在栈中开辟了一个short类型的空间,而1是int类型,
int类型比short类型大,所以相加后的结果应为比较大的类型,把s1+1的结果赋予short类型的变量s1,固然需要强行转化;
第二种方式:
short s1 = 1; s1 += 1;(可以正确编译)
由于+=运算符有自加功能,定义short s1 = 1;时,开辟了一个空间,当通过+=运算符运算时,只是在原来的栈中进行运算,不需强行转化;
附:java运算符的“提升”现象(运算规则)
    在java的算术运算符中要特别主要“提升”(thinking in java)现象,只要类型比int 小(即char byte short)那么在运算之前会自动转换为int.这样一来,最终生成的结果是int 类型。
eg1:  byte b1=10;
     byte b2=20;
     byte n3=b1+b2;
编译不了,报错:Type mismatch: cannot convert from int to byte
应该是:byte n3=(byte)b1+b2; 同理byte 和short.
   因此如果想要把结果赋值给较小的类型,就必须使用类型转换。通常,表达式中出现较大的数据类型决定了表达式最终结果的数据类型。
   继续解释:当使用+=、-=、*=、/=、%=、运算符对基本类型进行运算时,遵循如下规则:
• 运算符右边的数值将首先被强制转换成与运算符左边数值相同的类型,然后再执行运算,
且运算结果与运算符左边数值类型相同。
在s1=s1+1;中,s1+1
运算的结果是int型,把它赋值给一个 short型变量s1,所以会报错;而在s1+=1;中,由于
是s1是short类型的,所以1首先被强制转换为short型,然后再参与运算,并且结果也是
short类型的,因此不会报错。那么,s1=1+1;为什么不报错呢?这是因为1+1是个编译时可
以确定的常量,“+”运算在编译时就被执行了,而不是在程序执行的时候,这个语句的效果
等同于s1=2,所以不会报错。前面讲过了,对基本类型执行强制类型转换可能得出错误的
结果,因此在使用+=、 -=、*=、/=、%=等运算符时,要多加注意。
修改方法1:s1 = (short)(s1 + 1)
    方法2:s1 = (short)(s1 + (short)1)

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
对于short s1 = 1; s1 = s1 + 1; 由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。

对于short s1 = 1; s1 += 1;由于 += 是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
short s1 = 1;s1 = s1 + 1;意思是将数值1赋给short型变量s1,然后又将s1加1的值再赋给s1。因为数值型数据默认是int类型的,将计算出来的结果赋给short型变量会出现精度丢失的情况。所以编译的时候会报错。

short s1 = 1;s1 += 1;意思是将数值1赋给short型变量s1,s1+=1;相当于s1 = s1 =1;这里有一个自动类型转换提升的过程,从short类型自动转换成int类型,又低到高的转换。所以编译成功。

评分

参与人数 1黑马币 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马