Java提供了两种右移运算符:>> 和 >>>。其中,>>被称为有符号右移运算符,>>>被称为无符号右移运算符。他们的功能时将参与运算的对象对应的二进制数右移指定的位数。二者不同点在于>>在执行右移操作时,若参与运算的数字为正数,则在高位补零;若为负数,则在高位补1。而>>>则不同,无论参数运算的数字为正数还是负数,在执行运算时,都会在高位补0。
在对char, bute, short等类型的数进行位移操作前,编译器都会自动地将数值转化为int型,然后才进行位移操作。由于int型变量只占用了4Byte(32bit),因此,当右移的位数超过32bit时,移位运算没有任何意义。所以,在java语言中,为了保证以移动位数的有效性,以使右移的位数不超过32bit,采用了取余的操作,即a>>n等价于a>>(n%32)。
对于short类型来说,由于short只占了2Byte,在移位操作时会先转换为int类型,虽然在进行无符号右移时会在高位补1,但当运算完毕把结果再赋值给short类型变量时,只会取其中低位的两个字节。因此,高位无论补0还是补1对运算结果无影响。例如:-4的二进制表示为11111111 11111100(负数以补码的形式存储),在进行位移运算时,先转换为4Byte的int型并且高位补1,因此输出为11111111 11111111 11111111 11111100,在执行>>>无符号右移后其二进制变为011111111 11111111 11111111 11111110,当把运算结果再赋值给short变量时,只取底位的两个字节,因此运算后的二进制表示为:11111111 11111110,对应的十进制为-2。
引申:<<运算符与>>运算符有什么异同?
<<运算符表示左移,左移n位表示原来的值乘2的n次方。该操作经常用于代替乘法操作,由于CPU能够直接进行位运算操作,因此位运算比乘法运算的效率更高。
与右移不同的是,左移运算没有有符号和无符号的区别。在左移时,移除高位的同时在低位补0。例如:以(int) 4<<3为例,其运算步骤如下所述:
- 把4转换为二进制数00000000 00000000 00000000 00000100。
- 把该数字的高三位移走,同时其他位向左移动3位。
- 在最低位补3个零。最终结果为00000000 00000000 00000000 00100000,对应的十进制数位32(即4*2^3)。
与位移运算符相同的是,当进行左移运算时,如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模,例如对int型移动33位,实际上只会移动33%32=1位。