Java Multicasting(多次类型转换)拼图
找到程序的输出
public class Multicast {
public static void main(String[] args) {
System.out.println((int) (char) (byte) -1);
}
}
无论您以何种方式分割它,这个程序都会让人感到困惑。它从 int 值 -1 开始,然后将 int 转换为一个字节,然后转换为一个 char,最后再转换为一个 int。第一次强制转换将值从 32 位缩小到 8,第二次将其从 8 位扩大到 16,最后一次强制转换将其从 16 位扩大到 32。这个值最终会回到它开始的地方吗?如果你运行程序,你会发现它没有。它打印65535
让我们逐步理解这一点:-
1.程序的行为严重依赖强制转换的符号扩展行为。 Java使用二进制补码算法,因此 int 值 -1 设置了所有 32 位。
2.从 int 到 byte 的转换很简单。它执行一个缩小的原始转换,除了低位 8 位之外,它只是简单地去掉所有位。这留下了一个所有 8 位都设置的字节值,它(仍然)表示 -1。
3.从 byte 到 char 的转换比较棘手,因为 byte 是有符号类型而 char unsigned 。通常可以在保留数值的同时从一种整数类型转换为更宽的类型,但不可能将负字节值表示为 char。因此,从byte到char的转换不被认为是加宽原语转换,而是加宽和变窄原语转换:byte转换为int,int转换为char。
所有这些听起来可能有点复杂。幸运的是,有一个简单的规则描述了从窄整数类型转换为宽整数类型时的符号扩展行为:如果原始值的类型是有符号的,则执行符号扩展;如果它是一个字符,则零扩展,不管它被转换成什么类型。知道这个规则可以很容易地解决这个难题。因为 byte 是有符号类型,所以在将字节值 -1 转换为 char 时会发生符号扩展。结果 char 值设置了所有 16 位,因此它等于 65,535。
4.从 char 到 int 的强制转换也是一种扩大的原语转换,因此规则告诉我们执行零扩展而不是符号扩展。
生成的 int 值为 65535,这正是程序打印的内容。
参考:
Java益智书