【java解惑】多重强转引发的问题


   如下代码:

public class Example006 {

	public static void main(String[] args) {
		System.out.println("(byte) -1 = " + (byte) -1);
		// System.out.println("(char) -1 = " + (char) -1);
		// System.out.println("(char)((byte) -1) = " + (char) ((byte) -1));
		System.out.println("(int)((char)((byte) -1)) = "
				+ (int) ((char) ((byte) -1)));
	}
}


    输出结果:

(byte) -1 = -1
(int)((char)((byte) -1)) = 65535


    原因分析:

    该程序的行为紧密依赖于转型的符号扩展行为。Java 使用了基于 2 的补码的二进制运算,因此 int 类型的数值-1 的所有 32 位都是置位的(补码:正数同原码,负数符号位不变,其他位取反后加以,所以-1的所有32位都为1)。从 int 到 byte 的转型是很简单的,它执行了一个窄化原始类型转化 直接将除低 8 位之外的所有位全部砍掉。这样做留下的是一个8位都被置位了的 byte,它仍旧表示-1(8个1)。

    从 byte 到 char 的转型稍微麻烦一点,因为 byte 是一个有符号类型,而 char是一个无符号类型。在将一个整数类型转换成另一个宽度更宽的整数类型时, 通常是可以保持其数值的,但是却不可能将一个负的 byte 数值表示成一个 char。因此, 从 byte 到 char 的转换被认为不是一个拓宽原始类型转换,而是一个拓宽并窄化原始类型的转换:byte 被转换成了 int,而这个 int 又被转换成了 char。

    有一条很简单的规则能够描述从较窄的整型转换成较宽的整型时的符号扩展行为:如果最初的数值类型是有符号的,那么就执行符号扩展;如果它是 char,那么不管它将要被转换成什么类型,都执行

零扩展。 

    因为 byte 是一个有符号的类型,所以在将 byte 数值-1 转换成char 时,会发生符号扩展。作为结果的 char 数值的16 个位就都被置位了,因此它等于 2^16-1,即 65535。从 char 到 int 的转型也是一个拓宽原始类型转换,所以这条规则告诉我们,它将执行零扩展而不是符号扩展。作为结果的 int 数值也就成了65535,这正是程序打印出的结果。

    如果你在将一个 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);

      


更多参考资料:

1、关于Java符号扩展问题的解释:http://bbs.csdn.net/topics/310238373

2、补码至少介绍:http://baike.so.com/doc/4026477.html


(注:本【java解惑】系列,均是博主阅读《java解惑》原书后,将原书上的讲解和例子部分改编,然后写成博文进行发布的。所有例子均亲自测试通过,并共享在github上。通过这些例子,激励自己,惠及他人。同时,本系列所有博文会同步发布在博主个人微信公众号(搜索“爱题猿”或者“ape_it”),方便大家阅读。如果文中有任何侵犯原作者权利的内容,请及时告知博主,以便及时删除;如果读者对文中的内容有异议或者问题,欢迎通过博客留言或者微信公众号留言等方式共同探讨。)

源代码地址:https://github.com/rocwinger/java-disabuse


本文出自 “winger” 博客,谢绝转载!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值