《Java解惑》系列——01表达式之谜——谜题06:多重转型

来源:互联网 发布:鸟倦飞而知还什么意思 编辑:程序博客网 时间:2024/05/19 23:25

知识点:

注意java中的类型转换引起的:类型拓宽、窄化,符号扩展等。


问题:

下面程序会打印什么??


结果是不是出乎大家的意料呢?的确如此。
产生这个结果的原因:

无论你怎样分析这个程序,都会感到很迷惑。它以 int 数值-1开始,然后从int
转型为 byte,之后转型为 char,最后转型回 int。第一个转型将数值从32 位窄
化到了8位,第二个转型将数值从8位拓宽到了 16位,最后一个转型又将数值
从16位拓宽回了32 位。这个数值最终是回到了起点吗?如果你运行该程序,你
就会发现不是。它打印出来的是65535,但是这是为什么呢? 
该程序的行为紧密依赖于转型的符号扩展行为。Java 使用了基于 2 的补码的二
进制运算,因此 int类型的数值-1 的所有32 位都是置位的。从int到byte的
转型是很简单的,它执行了一个窄化原始类型转化(narrowing primitive
conversion),直接将除低8位之外的所有位全部砍掉。这样做留下的是一个8
位都被置位了的 byte,它仍旧表示-1。  
从byte 到 char 的转型稍微麻烦一点,因为 byte 是一个有符号类型,而 char
是一个无符号类型。在将一个整数类型转换成另一个宽度更宽的整数类型时,通
常是可以保持其数值的,但是却不可能将一个负的 byte 数值表示成一个 char。
因此,从byte 到 char 的转换被认为不是一个拓宽原始类型的转换,而是一个拓
宽并窄化原始类型的转换(widening and narrowing primitive conversion):
byte 被转换成了 int,而这个 int又被转换成了 char。 
所有这些听起来有点复杂,幸运的是,有一条很简单的规则能够描述从较窄的整
型转换成较宽的整型时的符号扩展行为:如果最初的数值类型是有符号的,那么
就执行符号扩展;如果它是char,那么不管它将要被转换成什么类型,都执行
零扩展。了解这条规则可以使我们很容易地解决这个谜题。  
因为byte是一个有符号的类型,所以在将byte数值-1转换成char时,会发生
符号扩展。作为结果的char数值的16个位就都被置位了,因此它等于216-1,
即 65535。从char到int的转型也是一个拓宽原始类型转换,所以这条规则告
诉我们,它将执行零扩展而不是符号扩展。作为结果的int数值也就成了65535,
这正是程序打印出的结果。  
尽管这条简单的规则描述了在有符号和无符号整型之间进行拓宽原始类型时的
符号扩展行为,你最好还是不要编写出依赖于它的程序。如果你正在执行一个转
型到 char 或从char 转型的拓宽原始类型转换,并且这个 char 是仅有的无符号
整型,那么你最好将你的意图明确地表达出来。 


解决方法:

转换之前,明确你自己的意图。否则就容易得到你意想不到的结果。

如果你在将一个 char 数值 c 转型为一个宽度更宽的类型,并且你不希望有符号
扩展,那么为清晰表达意图,可以考虑使用一个位掩码,即使它并不是必需的:  
int i = c & 0xffff;
或者,书写一句注释来描述转换的行为:  
int i = c; //不会执行符号扩展
如果你在将一个 char数值 c 转型为一个宽度更宽的整型,并且你希望有符号扩
展,那么就先将 char 转型为一个 short,它与 char 具有同样的宽度,但是它是
有符号的。在给出了这种细微的代码之后,你应该也为它书写一句注释:  
int i = (short) c; //转型将引起符号扩展
如果你在将一个byte数值b转型为一个char,并且你不希望有符号扩展,那么
你必须使用一个位掩码来限制它。这是一种通用做法,所以不需要任何注释:  
char c = (char) (b & 0xff);

总结:


这个教训很简单:如果你通过观察不能确定程序将要做什么,那么它做的就很有
可能不是你想要的。要为明白清晰地表达你的意图而努力。尽管有这么一条简单
的规则,描述了涉及有符号和无符号整型拓宽转换的符号扩展行为,但是大多数
程序员都不知道它。如果你的程序依赖于它,那么你就应该把你的意图表达清楚。 



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 热水器出热水小怎么办 天然气热水器水压不够怎么办 热水器水变小了怎么办 液压齿轮泵没力怎么办 gps总是浮点解怎么办 电源要做到稳压怎么办 变压器输出电压低怎么办 变压器输出电压高怎么办 家里空调带不动怎么办 小天才定位不准怎么办 伐木锯链条不出油怎么办 角磨机切割片卸不下来怎么办 油泵电机声音大怎么办 汽车油泵声音大怎么办 水泵电机噪音大怎么办 注塑机油泵超载怎么办 模具老是粘模怎么办 打印机提示卡纸2怎么办 扬子空调显示e9怎么办 供应商不配合售后怎么办? 数控车床显示屏不亮怎么办? 西威变频器过载怎么办 vgm申报错了怎么办 老公常年不回家怎么办 狗对主人龇牙怎么办 酒喝多了会尿床怎么办 6岁儿童尿床怎么办 遇到耍酒疯的人怎么办 老公喝完酒尿床怎么办 尿不尽影响睡觉怎么办 大便次数较多怎么办 吃的少拉不出来怎么办 吃奶的狗拉肚子怎么办 高跟鞋头折了怎么办 新生儿胯下破皮怎么办 led变压器坏了怎么办 家里电路烧坏了怎么办 接触器线圈烧了怎么办 凯恩帝准备未绪怎么办 冰箱按键没反应怎么办 触摸屏摔坏了怎么办