由于字节在java中是有符号的,为了获得无符号整数值,我们用0xFF作为掩码:
byte signed = -1;// -—> 0b11111111
int unsigned = signed & 0xFF;// —-> 0b11111111 & 0b11111111
System.out.println(“unsigned: ”+unsigned);//prints 255 instead of -1 since we masked earlier
但是当无符号的
int
被转换为一个字节时,它似乎没有发生任何事情,即
byte resigned = (byte) unsigned;
System.out.println(“resigned: ”+resigned);//same value as earlier signed = -1
仔细观察初始操作
int unsigned = signed & 0xFF;// the result of 0b11111111 & 0b11111111 is actually = 0b11111111
即使签名的值是我们拥有的其他东西
byte signed = -44;// -—> 0b11010100
int unsigned = signed & 0xFF;// the result of 0b11010100 & 0b11111111 is still actually = 0b11010100
byte resigned = (byte) unsigned;
System.out.println(“resigned: ”+resigned);//same value as signed = -44
因此,对于无符号
int
来说,实际有符号值似乎没有发生任何变化。
掩码实际上对整数的(字节)值有任何作用吗?或者它只是标记
javac
应如何处理整数的一种方法?
byte signed = -1;// -—> 0b11111111
正确。
int unsigned = signed & 0xFF;// —-> 0b11111111 & 0b11111111
这是不正确的。有3个步骤。
signed
的值转换(符号扩展)为int
;即 0b11111111
变为 0b11111111111111111111111111111111
(= 0xFFFFFFFF)
将
0b11111111111111111111111111111111
(= 0xFFFFFFFF
) 与 0b00000000000000000000000011111111
(= 0x000000FF
) 进行与运算,得到 0b00000000000000000000000011111111
(= 0x000000FF
)`
0b00000000000000000000000011111111
(= 0x000000FF
) 被分配给 unsigned
。
(注意:完整地写出这一点很重要,以便您了解发生了什么。)
byte resigned = (byte) unsigned;
这里也有两个步骤。
演员表
(byte)
转换 0b00000000000000000000000011111111
(= 0x000000FF
)
到 0b11111111
(= 0xFF
) 即它将 int
转换为 byte
。
然后字节
0b11111111
(= 0xFF
) 被分配给resigned
。
因此,对于 unsigned int 来说,实际有符号值似乎没有发生任何变化。
但是确实发生了一些事情!
&
运算符以符号扩展值 0b11111111111111111111111111111111
(代表 -1)开始,并将其转换为 0b00000000000000000000000011111111
(代表 255)。
您可以通过运行以下命令来验证是否发生了某些事情:
byte signed = -1; // -—> 0b11111111
int x = signed;
System.out.println("x: " + x); // prints -1
最终得到的值与开始时的值相同并不意味着什么都没有发生。确实发生了一些事情。您将
byte
值 -1
转换为 int
值 255
,然后将其转换回字节 -1
。
您还可以通过阅读 Java 语言规范的相关部分来验证这一点。 (如果您需要参考资料,请告诉我。)
掩码实际上对整数的(字节)值有什么作用,还是只是标记 javac 应如何处理整数的一种方法?
屏蔽确实起到了作用。
如果您查看
javac
编译器生成的字节码,您会看到执行 byte
到 int
转换、屏蔽和赋值的代码。然后在另一个方向,您会看到一个字节码来进行 int
到 byte
的转换。
但是,这是一个实现细节。