java解惑之表达式之谜(谜题6)

谜题6:多重转型

当程序连续使用多个转型时,会发生什么呢?看下面示例代码:

public class Multicast{

public static void main(String[] args){

System.out.println((int)(char)(byte) -1);

}

}

转换的顺序是从开始的int数值转为byte,再转为char,最后又转回int。那么最后打印的结果会是原来的-1么?当执行程序后就会发现,打印的是65535。从第一次转换开始,数值从32位变窄为8位,再扩宽为16,最后又扩宽为32位,但结果却不是原来的数值,这是为什么呢?

我们对三个转型一次做解析:从int到byte的转型执行了一个窄化原生类型的转换,直接将除低8位之外的所有位全部砍掉(java使用了基于2的补码的二进制运算,因此int类型的数值-1的所有32位都是置位的)。这次转换后,数值仍旧是-1;在byte到char的转型中,因为byte是有符号类型,而char是无符号类型。这时,转型是扩宽的,所以数值是能正确转型的,但却不能用char来表示一个负的byte数值。因为,从byte到char的转换不是一个扩宽原生类型转换,而是一个扩宽并窄化原生类型的转换(即先从byte先转换成int,再从int转换成char)。对于这种转型,有一条简单的规则来对其进行描述:如果最初的数值类型是有符号的,那么就执行符号扩展;如果它是char,那么不管它将要被转换成什么类型,都执行零扩展。所以,当数值-1从byte转换成char时,会发生符号扩展。作为结果的char数值的16位就都被置位了,因此它等于2^16-1,即65535,最后打印出的数值也正是这个。

因此,如果你在将一个char数值c转型为一个宽度更宽的类型,并且不希望有符号扩展,那么清晰表达意图,可以考虑使用一个位掩码,即使它并不是必需的:  int i = c & 0xffff;或者写一句注释来描述转型的行为。

如果你在将一个char数值转型为一个宽度更宽的整型,并且希望有符号扩展,那么就先将char转型为一个short,它与char具有同样的宽度,但是它是有符号的,并写好注释;

如果你在将一个byte数值b转型为一个char,并且不希望有符号扩展,那么必需使用一个位掩码来限制它,这是一种通用做法,不需要任何注释:  char c = (char) (b & 0xff);

如果你在将一个byte数值转换为char,并且希望有符号扩展,也应该写一条注释来进行说明、

总的来说,如果你通过观察不能确定程序将要做什么,那么它做的就很可能不是你想要的。所以我们就应该把自己的意图表达清楚,来避免犯错。

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值