AQU*_*AQU 3 java byte-shifting
我正在使用Java。我想知道为什么Java会产生此输出。我在这里分享代码。
public class vvn {
public static void main(String[] args)
{
byte [] arr = new byte[4];
arr[0] = (byte)157;
arr[1] = 1;
arr[2] = 0;
arr[3] = 0;
System.out.format("read 0x%x 0x%x 0x%x 0x%x \n",arr[3],arr[2],arr[1],arr[0]);
int v = (arr[0] | (arr[1] << 8) | (arr[2] << 16) | (arr[3] << 24));
System.out.format("read 0x%x\n",v);
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出为
read 0x0 0x0 0x1 0x9d
read 0xffffff9d
Run Code Online (Sandbox Code Playgroud)
我预计输出应为0x0000019d
您正在从字节(有符号的8位)转换为整数(有符号的32位)。最高有效位(最左边的一位)保持符号(请参见2的补码)。
您157是10011101二进制文件。由于您将此值分配给有符号字节(java没有无符号字节),因此实际上这是一个负数-99。
现在,当您从字节转换为整数时,将保留该值。在负数的情况下,这意味着将所有位设置为左侧以保留有符号性。就您而言,10011101变为11111111 11111111 11111111 10011101。
无论如何,在Java中使用无符号字节是一场噩梦。基本上,您需要使用0xff屏蔽所有内容(以切断“左侧的对象”),如下所示:
int v = ((arr[0] & 0xff) |
((arr[1] & 0xff) << 8) |
((arr[2] & 0xff) << 16) |
((arr[3] & 0xff) << 24));
Run Code Online (Sandbox Code Playgroud)
美丽,不是吗?
更新1:另外,您可能对Guava的UnsignedBytes感兴趣...
更新2: Java 8字节具有toUnsignedInt()和toUnsignedLong()方法。这样,您的计算将变为:
int v = (Byte.toUnsignedInt(arr[0]) |
(Byte.toUnsignedInt(arr[1]) << 8) |
(Byte.toUnsignedInt(arr[2]) << 16) |
(Byte.toUnsignedInt(arr[3]) << 24));
Run Code Online (Sandbox Code Playgroud)