位操作符(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<
因此,如果对一个int 型,进行移位,x<
int a = 140;
System.out.println(Integer.toBinaryString(a));
a <<= 34;
System.out.println(Integer.toBinaryString(a));
上面那两个语句的执行过程是:
先把 34换算成二进制:100010,对该二进制取低5位,即00010,再换算成十进制数:2,所以实际上是对a左移两位,所以上面程序的输出结果为:
10001100
1000110000
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 -1
the binary of b is 11111111111111111111111111111111
b is -1
the binary of b is 11111111111111111111111111111111
b is -1
the binary of b is 11111111111111111111111111111111
b >>> 10 is 4194303
the 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 = 2147483647
bigger = -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 以外,任何一种基本类型都可通过类型转换变为其他基本类型。