半斤

现在该轮到你来写些代码了,好消息是,你只需为这个谜题编写两行代码,并为
下一个谜题也编写两行代码。这有什么难的呢?我们给出一个对变量 x 和 i 的声
明即可,它肯定是一个合法的语句:  
x += i; 
但是,它并不是:  
x = x + i; 
许多程序员都会认为该迷题中的第一个表达式 (x += i)只是第二个表达式 (x = 
x + i)的简写方式。但是这并不十分准确。这两个表达式都被称为赋值表达式。
第二条语句使用的是简单赋值操作符 (=),而第一条语句使用的是复合赋值操
作符。(复合赋值操作符包括 +=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=
和|=)Java 语言规范中讲到,复合赋值 E1 op= E2 等价于简单赋值E1 = 
(T)((E1)op(E2)),其中T 是 E1 的类型,除非E1 只被计算一次。  

换句话说,复 合赋值表达式自动地将它们所执行的计算的结果转型为其左侧变量
的类型。如果结果的类型与该变量的类型相同,那么这个转型不会造成任何影响。
然而,如果结果的类型比该变量的类型要宽,那么复合赋值操作符将悄悄地执行
一个窄化原始类型转换。因此,我们有很好的理由去解释为什么在尝试着执行等
价的简单赋值可能会产生一个编译错误。  

为了说得具体一些,并提供一个解决方案给这个谜题,假设我们在该谜题的两个
赋值表达式之前有下面这些声明:  

short x = 0; 
int i = 123456 ; 
复合赋值编译将不会产生任何错误:  
x += i; // 包含了一个隐藏的转型! 
你可能期望 x 的值在这条语句执行之后是 123,456,但是并非如此l,它的值是
-7,616。int类型的数值 123456 对于 short 来说太大了。自动产生的转型悄悄
地把 int 数值的高两位给截掉了。这也许就不是你想要的了。  

相对应的简单赋值是非法的,因为它试图将int 数值赋值给 short变量,它需要
一个显式的转型:  

x = x + i; // 不要编译——  “可能会丢掉精度” 
这应该是明显的,复合赋值表达式可能是很危险的。为了避免这种令人不快的突
袭,请不要将复 合赋值操作符作用于byte、short 或 char 类型的变量上。在将
复合赋值操作符作用于 int类型的变量上时,要确保表达式右侧不是long、float
或 double类型。在将复合赋值操作符作用于 float类型的变量上时,要确保表
达式右侧不是 double类型。这些规则足以防止编译器产生危险的窄化转型。  

总之,复合赋值操作符会悄悄地产生一个转型。如果计算结果的类型宽于变量的
类型,那么所产生的转型就是一个危险的窄化转型。这样的转型可能会悄悄地丢
弃掉精度或数量值。对语言设计者来说,也许让复合赋值操作符产生一个不可见
的转型本身就是一个错误;对于在复合赋值中的变量类型比计算结果窄的情况,
也许应该让其非法才对。
  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值