最近在重温 Java 基础的过程中,使用 >>>(无符号右移)运算符对 byte 类型和 short 类型的负数进行运算时,发现一些细节之处。
总结:
- >>> 对于正数的运算,同 >> 运算符;
- >>> 对于负数的运算,会把 byte 、short 类型转换为 int 类型进行运算(补齐32位), 再对低位截取来完成类型的还原过程。
示例:
byte 计算示例: byte b1 = -1; byte b2 = b1 >>> 10; -1 的二进制: 原码为 1000 0001 补码为 1111 1110 反码为 1111 1111 运算时转换为 int 类型(补齐32位) 运算时反码为 1111 1111 1111 1111 1111 1111 1111 1111 运算后反码为 0000 0000 0011 1111 1111 1111 1111 1111 |(舍弃)11 1111 1111 低位截取8位(byte)后反码为 1111 1111 低位截取8位(byte)后补码为 1111 1110 低位截取8位(byte)后原码为 1000 0001 最后的十进制结果为 -1 short 计算示例: short s1 = -1; short s2 = s1 >>> 10; -1 的二进制: 原码为 1000 0000 0000 0001 补码为 1111 1111 1111 1110 反码为 1111 1111 1111 1111 运算时转换为 int 类型(补齐32位) 运算时反码为 1111 1111 1111 1111 1111 1111 1111 1111 运算后反码为 0000 0000 0011 1111 1111 1111 1111 1111 |(舍弃)11 1111 1111 低位截取16位(short)后反码为 1111 1111 1111 1111 低位截取16位(short)后补码为 1111 1111 1111 1110 低位截取16位(short)后原码为 1000 0000 0000 0001 最后的十进制结果为 -1
示例代码:
/*
>>> 左边是 byte 类型,右边是 int 类型,结果用一个 byte 类型接收:
因为参数是 byte 类型,所以计算结果被低位截取了,十进制为 -3 ,二进制为 1000 0011 。
*/
byte num1 = -10;
byte num2 = (byte) (num1 >>> 2);
/*
>>> 左边是 byte 类型,右边是 int 类型,结果用一个 int 类型接收:
因为参数是 int 类型,所以计算结不会被低位截取,十进制为 1073741821 ,二进制为 0011 1111 1111 1111 1111 1111 1111 1101 。
*/
byte num3 = -10;
int num4 = num3 >>> 2;
/*
>>> 左边是 short 类型,右边是 int 类型,结果用一个 short 类型接收:
因为参数是 short 类型,所以计算结果被低位截取了,十进制为 -3 ,二进制为 1000 0000 0000 0011 。
*/
short num5 = -10;
short num6 = (short) (num5 >>> 2);
/*
>>> 左边是 short 类型,右边是 int 类型,结果用一个 int 类型接收:
因为参数是 int 类型,所以计算结不会被低位截取,十进制为 1073741821 ,二进制为 0011 1111 1111 1111 1111 1111 1111 1101 。
*/
short num7 = -10;
int num8 = num7 >>> 2;