我们可以在Java中制作无符号字节吗?

2022-08-31 06:08:46

我正在尝试将有符号字节转换为无符号。问题是我收到的数据是无符号的,Java不支持无符号字节,所以当它读取数据时,它会将其视为有符号。

我尝试通过我从Stack Overflow获得的以下解决方案来转换它。

public static int unsignedToBytes(byte a)
{
    int b = a & 0xFF;
    return b;
}

但是当它再次以字节为单位转换时,我得到相同的签名数据。我正在尝试将此数据用作仅接受字节作为参数的Java函数的参数,因此我无法使用任何其他数据类型。如何解决此问题?


答案 1

原语在Java中签名的事实与它们在内存/传输中的表示方式无关 - 一个字节只有8位,你是否将其解释为有符号范围取决于你。没有神奇的旗帜说“这是签名的”或“这是未签名的”。

当对原语进行签名时,Java 编译器将阻止您将高于 +127 的值分配给字节(或小于 -128)。但是,没有什么可以阻止您为了实现这一目标而向下转换int(或短整型):

int i = 200; // 0000 0000 0000 0000 0000 0000 1100 1000 (200)
byte b = (byte) 200; // 1100 1000 (-56 by Java specification, 200 by convention)

/*
 * Will print a negative int -56 because upcasting byte to int does
 * so called "sign extension" which yields those bits:
 * 1111 1111 1111 1111 1111 1111 1100 1000 (-56)
 *
 * But you could still choose to interpret this as +200.
 */
System.out.println(b); // "-56"

/*
 * Will print a positive int 200 because bitwise AND with 0xFF will
 * zero all the 24 most significant bits that:
 * a) were added during upcasting to int which took place silently
 *    just before evaluating the bitwise AND operator.
 *    So the `b & 0xFF` is equivalent with `((int) b) & 0xFF`.
 * b) were set to 1s because of "sign extension" during the upcasting
 *
 * 1111 1111 1111 1111 1111 1111 1100 1000 (the int)
 * &
 * 0000 0000 0000 0000 0000 0000 1111 1111 (the 0xFF)
 * =======================================
 * 0000 0000 0000 0000 0000 0000 1100 1000 (200)
 */
System.out.println(b & 0xFF); // "200"

/*
 * You would typically do this *within* the method that expected an 
 * unsigned byte and the advantage is you apply `0xFF` only once
 * and than you use the `unsignedByte` variable in all your bitwise
 * operations.
 *
 * You could use any integer type longer than `byte` for the `unsignedByte` variable,
 * i.e. `short`, `int`, `long` and even `char`, but during bitwise operations
 * it would get casted to `int` anyway.
 */
void printUnsignedByte(byte b) {
    int unsignedByte = b & 0xFF;
    System.out.println(unsignedByte); // "200"
}

答案 2

我不确定我是否理解你的问题。

我刚刚尝试了这个,对于字节-12(有符号值),它返回整数244(相当于无符号字节值,但键入为):int

  public static int unsignedToBytes(byte b) {
    return b & 0xFF;
  }

  public static void main(String[] args) {
    System.out.println(unsignedToBytes((byte) -12));
  }

这是你想做的吗?

Java 不允许像 C 那样将 244 表示为值。要表示高于 (127) 的正整数,您必须使用不同的整数类型,如 、 或 。byteByte.MAX_VALUEshortintlong


推荐