以下是我一直在关注的一些代码:
public static long getUnsignedInt(ByteBuffer buff) {
return (long) (buff.getInt() & 0xffffffffL);
}
有没有理由buff.getInt() & 0xffffffffL
(0xffffffffL
在32个最低有效位中有32位1?在我看来,结果总是buff.getInt()
。
答案 0 :(得分:8)
简而言之,这是因为该方法需要将签名的 int
(所有Java int
都转换为无符号数量
如果您只是(long) buff.getInt()
,而buff.getInt()
返回-1
,则最终会得到-1
。这是签名数量 - 而不是该方法应该返回的数量。
因此,该方法所做的是通过将buff.getInt()
位与int
进行AND运算来强制0x00000000FFFFFFFF
成为无符号。这有效地将签名的int
的位“重新解释”为无符号int
(实际上是有符号的long
,但由于只有低32位将被设置,因此它可以作为无符号int
),产生所需的结果。
例如,(为了简洁起见,使用字节)。
说buff.getInt()
确实是buff.getByte()
,并返回-1 == 0xFF
尝试将其转换为int
,由于符号扩展的魔力,您最终会得到0xFFFFFFFF
- 仍为-1
。
但是,使用0xFF
进行屏蔽,最后会得到0x000000FF
== 255 - 所需的值。
我相信显式演员是不必要的(它不在我的机器上),但我可能会遗漏某些东西......
编辑:实际上 是不必要的。来自JLS第5.6.2节:
应用扩展基元转换(第5.1.2节)来转换以下规则指定的一个或两个操作数:
double
,则另一个操作数将转换为double
。float
,则另一个操作数将转换为float
。long
,则另一个操作数将转换为long
。int
类型。答案 1 :(得分:3)
如果buff.getInt()
为负数,则将其强制转换为长数时仍为负数。但它会被延长。
所以,如果你想保留比特模式,例如为了尝试将值解释为无符号值,&0xffffffffL
将掩盖这些位。
e.g。如果buff.getInt()返回-2147483648,则返回的int将具有0x80000000的位模式。转为长,那仍然是-2147483648,但有点模式0xffffffff80000000。 0xffffffff80000000 & 0xFFFFFFFF
保留原始位模式0x80000000
答案 2 :(得分:2)
Java中的整数(int
和long
)是已签名的two's complement个数字。这意味着如果数字为正数(或0),则高位数为0;如果数字为负数,则为-1。
要从int
转换为long
,Java会使用符号扩展名。这意味着它所填写的数字"左边依赖于最左边的数字。为了说明从4位到8位的数字:
因此,如果您想将1111
解释为带符号的数字(即15),则无法将其从4位转换为8位:您将获得1111 1111
,这是-1。你想要的是0000 1111
,即15。
为此,您需要对数字执行按位AND以屏蔽已填入的高位,并将其转换为0。