接下来看看蛋疼的转型,或者强制转换。 转型是用于将一个数值从一种类型转换到另一种类型。 一般我们转换一次就够了,但是如果连续转型会发生什么变化呢? 来个例子: public class Multicast{ public static void main (String[] args){ system.out.println((int)(char)(byte -1)); } } 它以int-1开始,从int转换为byte,再从byte转换成char,最后转回int。第一步从32位转化为8位,第二部从8位扩充到16位,第三步从16位扩充为32位。它最终会打印出来-1么?它最终会打印出来65535。 原因:转型有符号扩展行为。Java是基于补码的运算,所以int-1的所有32位都是置位的。第一步转化只保留了低8位,任然是byte类型的-1;第二步byte转char因为char是无符号类型,所以byte转char会发生符号扩展,作为结果的char数值的16位就都被置位了,其值等于2^16-1=65535;第三步此值就又转换成int类型了。 结论:如果最初数值类型是有符号的,会执行符号扩展;如果是char,不管它将要被转换成什么类型,都执行零扩展。 如果你想将char转换成无符号的更宽的类型,可以使用一位掩码: int i=c&0xffff; 如果你想将char转换成有符号的更宽的类型,可以先将char转换为short,short与char有相同宽度但有符号: int i=(short) c; 如果你想将byte转换成char且不希望有符号扩展,那必须用一位掩码来限制它: char c=(char)(b&0xff); 如果你想将byte转换成char且希望有符号扩展,直接写上注释: char c=(char)b;//sign extension is performed 我记得当初刚开始学C++没多久的时候,老师当堂问过我们一个问题。就是个很简单的变量值互换的问题,设置一个中间变量就行。但是紧接着老师问我们如果禁止用中间变量怎么办。当时好像没人能答得上来,最后老师给我们讲了位操作。我第一次认识到离散数学的威力。 看一个比较好玩的例子,现在大部分都不这么写了吧,起码得加注释。 public class CleverSwap{ public static void main(String[]args){ int x=1984; /(0x7c0) int y=2001; /(0x7d1) x^=y^=X^=y; System.out.println("x="+x+"y="+y); } } 那么问题来了,挖掘机到底......不是,它能互换x和y么? 肯定是不能的,因为它看起来这么正常,嘿嘿...... 打印出来是:x=0y=2984。 x=x^y; y=y^x; x=y^x; 看起来挺合理啊,Java里为什么失败了呢? 原因:Java中操作符的操作数是从左向右求值的。在上面的程序中x被提取了两次但是两次都在所有赋值操作之前。在C和C++中之所以可以是因为大部分编译器都是先计算再赋值的,从右往左。 结论:在单个表达式中不要对同一个变量赋值两次。
|