Chapter 3 操作符

来源:互联网 发布:windows 95 怎样开机 编辑:程序博客网 时间:2024/05/17 01:56

位操作符(bitwise operator)
位操作符允许我们操作一个基本数据类型中的整数型值的单个“比特(bit)”,即二进制位。

1)位操作符

按位“与”操作符(&)

按位“或”操作符(|)

按位“异或”操作符(^)

按位“非”操作符(~)

 

2)位操作符可与等号(=)联合使用,以便合并运算操作和赋值操作:&=,|=和^=都是合法的(由于~是一元操作符,所以不可与=联合使用)。

 

3)布尔类型(boolean)作为一种“单比特”值,可对它执行按位“与”、“或”和“异或”运算,但不能执行按位“非”(大概是为了避免与逻辑NOT 混淆)。对于布尔值,位操作符具有与逻辑操作符相同的效果,只是它们不会中途“短路”。

 

4)在移位表达式中,不能使用布尔运算。

 

 

 ———————————————————————————————————————————————————

 

移位操作符(shift operator)

1)移位操作符操作的运算对象也是二进制的“位”,但是它们只可以被用来处理整数类型(基本类型的一种)。

2)移位操作符

左移位操作符(<<)能将操作符左边的运算对象向左移动操作符右侧指定的位数(在低位补0)。

“有符号”右移位操作符(>>)则将操作符左边的运算对象向右移动操作符右侧指定的位数。“有符号”右移位操作符使用了“符号扩展”:若符号为正,则在高位插入0;若符号为负,则在高位插入1。

Java 中增加了一种“无符号”右移位操作符(>>>),它使用了“零扩展”:无论正负,都在高位插入0。

3)如果对 char、byte 或者short 类型的数值进行移位处理,那么在移位进行之前,它们会自动转换为int,并且得到的结果也是一个int 类型的值。而右侧操作数,作为真正移位的位数,只有其二进制表示中的低5 位才有用。这样可防止我们移位超过int 型值所具有的位数。(译注:因为2 的5 次方为32,而int 型值只有32 位)。若对一个long 类型的数值进行处理,最后得到的结果也是long。此时只会用到右侧操作数的低6 位,以防止移位超过long 型数值具有的位数。

对于上面红色部分的解释:

移位操作符操作的运算对象是二进制的“位”,int类型换算为二进制是32位,也就是2的5次幂 !如果移32位以上,那么原来的数的信息会全部丢失,这样也就没有什么意义了!所以上面的“而右侧操作数,作为真正移位的位数,只有其二进制表示中的低5 位才有用。”说的是:移位操作符右端的那个数(化成二进制)的低5位才有用(因为二进制的低五位全是1而其他位全为0时的数值为31),例如:
x<<y;
是指y的二进制的低5位才有用,即不能大于32;而对于long型也是同样的道理!


因此,如果对一个int 型,进行移位,x<<y:当y小于32时,移位后的结果一般都在我们的预料当中;而如果y大于32,由于移位超出了int所能表示的范围,这时就先把y化成二进制数,然后取该二进制数右端的低5位,再把这5位化成十进制,此时的这个十进制就是要对X移动的位数。例如:        

        int a = 140;        System.out.println(Integer.toBinaryString(a));        a <<= 34;        System.out.println(Integer.toBinaryString(a));

上面那两个语句的执行过程是:
先把 34换算成二进制:100010,对该二进制取低5位,即00010,再换算成十进制数:2,所以实际上是对a左移两位,所以上面程序的输出结果为:

100011001000110000

4)移位操作符可与等号(<<=或>>=或>>>=)组合使用。此时,操作符左边的值会移动由右边的值指定的位数,再将得到的结果赋回左边的变量。但在进行“无符号”右移结合赋值操作时,可能会遇到一个问题:如果对byte 或short 值进行这样的移位运算,得到的可能不是正确的结果。它们会先被转换成int 类型,再进行右移操作。然后被截断,赋值给原来的类型,在这种情况下可能得到-1 的结果,例如:


        byte b = -1;        System.out.println("b is " + b + "\nthe binary of b is " + Integer.toBinaryString(b));        b >>>= 10;        System.out.println("b is " + b + "\nthe binary of b is " + Integer.toBinaryString(b));        b = -1;        System.out.println("b is " + b + "\nthe binary of b is " + Integer.toBinaryString(b));        System.out                .println("b >>> 10 is " + (b >>> 10) + "\nthe binary of b >>> 10 is "                        + Integer.toBinaryString(b >>> 10));


在最后一个移位运算中,结果没有赋回给 b,而是直接打印出来,所以其结果是正确的。

上述程序的输出结果为:

b is -1the binary of b is 11111111111111111111111111111111b is -1the binary of b is 11111111111111111111111111111111b is -1the binary of b is 11111111111111111111111111111111b >>> 10 is 4194303the binary of b >>> 10 is 1111111111111111111111

 

———————————————————————————————————————————————————

 

操作符小结

1)对两个足够大的int 值执行乘法运算,结果会溢出,例如:

        int big = Integer.MAX_VALUE;        System.out.println("big = " + big);        int bigger = big * 4;        System.out.println("bigger = " + bigger);


输出结果为:

big = 2147483647bigger = -4

你不会从编译器那里收到任何出错或警告信息,运行时也不会出现异常。这说明Java 确实是好东西,却也没有“那么”好!

 

2)对于 char、byte 或者short,混合赋值并不需要类型转换,例如:

    void charTest(char x, char y) {        // Compound assignment:        x++;        x--;        x += y;        x -= y;        x *= y;        x /= y;        x %= y;        x <<= 1;        x >>= 1;        x >>>= 1;        x &= y;        x ^= y;        x |= y;    }


 3)除boolean 以外,任何一种基本类型都可通过类型转换变为其他基本类型。