【问题标题】:Converting bytes to a long: Why do some implementations bitwise-AND each byte with 0xff?将字节转换为长字节:为什么某些实现将每个字节按位与 0xff?
【发布时间】:2015-07-06 15:50:39
【问题描述】:

我正在看 SE6 中 java.ioDataInputStream.readLong() 的实现:

private byte readBuffer[] = new byte[8];

public final long readLong() throws IOException {
    readFully(readBuffer, 0, 8);
    return (((long)readBuffer[0] << 56) +
            ((long)(readBuffer[1] & 255) << 48) +
            ((long)(readBuffer[2] & 255) << 40) +
            ((long)(readBuffer[3] & 255) << 32) +
            ((long)(readBuffer[4] & 255) << 24) +
            ((readBuffer[5] & 255) << 16) +
            ((readBuffer[6] & 255) <<  8) +
            ((readBuffer[7] & 255) <<  0));

鉴于 readBuffer[] 是一个 bytes 数组,为什么&amp; 每个字节都需要 255?

当单个字节被转换为 long 时,不应该将 long 的剩余位 (9-64) 位自动设置为零,从而使 &amp; 变得不必要吗?

【问题讨论】:

  • 如果你将一个值为 0x81 的字节转换为一个 int,你会得到一个 0xFFFFFF81 的值。

标签: java type-conversion bit-manipulation byte long-integer


【解决方案1】:

java 的字节类型是有符号的,所以 0xff (255) == -1,在从 byte 扩展到 int/long 期间 - 保留有符号值,所以如果你只有代码:

final byte a = (byte)0xff;
final long b = a;

System.out.println(b); // output here is -1, not 255

所以,这里有一个技巧:

final byte a = (byte)0xff;
final long b = a & 0xff; // binary and between byte A and int 0xff

System.out.println(b); // output here is 255

所以,第一个字节变量a由于符号扩展而被提升为int(并变为0xffffffff),然后我们通过按位与截断它

【讨论】:

  • 这个答案很好扩展和清晰。特别考虑到 Java 是一种讨厌无符号的语言......我永远不会明白为什么 Java 会废除无符号。
  • 谢谢!我一直将“字节”解释为“一系列原始位”——我没有想到它可能是“(有符号的)8 位数字”。
【解决方案2】:

为了防止负值字节的符号扩展。

【讨论】:

  • @downvoter 这里有些错误?真的吗?有些人会对任何事情投反对票。
  • 我投了反对票,因为这是一个非常糟糕的答案。没错,但是没有示例,并且看到您的答案的二进制新手不会理解它。这有点像纯代码答案
  • @Jojodmo 在过去 44 年的任何时候我都会理解它。你的旅费可能会改变。它与纯代码答案完全不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 2015-08-11
  • 2012-07-05
  • 2018-06-24
  • 1970-01-01
相关资源
最近更新 更多