Java中的字节默认为有符号。我在其他帖子上看到一个方法可以使用以下代码来获得无符号字节:int num = (int) bite & 0xFF
请问能否有人解释一下为什么这个操作可以将有符号字节转换为无符号字节,然后再转换为相应的整数?用11111111进行按位与运算应该会得到相同的字节吧?
类型转换的优先级高于&
操作符。因此,您首先将其强制转换为int,然后进行AND运算以屏蔽掉所有设置的高位比特,包括Java使用的二进制补码符号位,留下原始字节的正值。例如:
let byte x = 11111111 = -1
then (int) x = 11111111 11111111 11111111 11111111
and x & 0xFF = 00000000 00000000 00000000 11111111 = 255
而您已经有效地从原始字节中删除了符号。
把一个字节与11111111进行AND运算会得到相同的字节,对吗?
但实际上你是在与00000000000000000000000011111111进行AND运算,因为0xFF是一个int字面量,在Java中没有byte字面量。所以,这个byte会被提升为int类型(强制类型转换是不必要的),然后它的符号被扩展了(即保留了byte的可能负值),但是通过与所有这些零进行AND运算,符号扩展被还原了。结果是一个int,其最低有效位恰好是原来的byte,因此它的值就像byte在无符号情况下的值一样。
& 0xFF
抛弃了“符号扩展”的位。可能值得一提... - aioobe在Java 8中,Byte类出现了这样的方法:
/**
* Converts the argument to an {@code int} by an unsigned
* conversion. In an unsigned conversion to an {@code int}, the
* high-order 24 bits of the {@code int} are zero and the
* low-order 8 bits are equal to the bits of the {@code byte} argument.
*
* Consequently, zero and positive {@code byte} values are mapped
* to a numerically equal {@code int} value and negative {@code
* byte} values are mapped to an {@code int} value equal to the
* input plus 2<sup>8</sup>.
*
* @param x the value to convert to an unsigned {@code int}
* @return the argument converted to {@code int} by an unsigned
* conversion
* @since 1.8
*/
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
如您所见,结果是一个int
而不是一个字节。
它是如何工作的呢?假设我们有一个byte b = -128;
,这被表示为1000 0000
,那么当您执行此行时会发生什么?让我们使用一个临时的int来解释一下,比如:
int i1 = (int)b;
现在i1是-128,实际上它的二进制表示如下:
1111 1111 1111 1111 1111 1111 1000 0000
i1 & 0xFF
在二进制下是什么样的呢?
1111 1111 1111 1111 1111 1111 1000 0000
&
0000 0000 0000 0000 0000 0000 1111 1111
0000 0000 0000 0000 0000 0000 1000 0000
这个值恰好是128,意味着您的有符号值转换为无符号值。
编辑
将字节-128 .. 127
转换为0 .. 255
int unsignedByte = 128 + yourByte;
使用一个字节无法表示128到255之间的值,您必须使用其他类型,例如int或smallint。
是的,但这样你可以确保你永远不会得到一个大于255或小于0的数字。
如果第一位是1,则该数字为负数。如果将字节转换为整数,如果它是负数,则会在前面添加1个字节,如果是正数,则添加0个字节。运行and例程将删除第一个8左侧的所有字节。这实际上会将256添加到负字节。
&
,我仍然会得到239
:System.out.println((int) (((byte) -17) & 0xFF));
- aioobe11111111
是 255。然而,当它被视为有符号数时,它是 -1。实际上,你的代码将其解释为无符号数,而不是有符号数(这是 Java 的默认设置)? - darksky