我试图转换一个无符号的有符号字节。问题是我接收的数据是无符号的,Java不支持无符号字节,所以当它读取数据时,它将其视为有符号的。

我尝试通过下面的解决方案转换它,我从Stack Overflow。

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

但是当它再次以字节为单位转换时,我得到了相同的带符号数据。我试图使用此数据作为参数的Java函数,只接受一个字节作为参数,所以我不能使用任何其他数据类型。我该如何解决这个问题?


当前回答

我不太明白你的问题。

我刚刚尝试了这一点,对于字节-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表示为字节值。MAX_VALUE(127)你必须使用不同的整型,如short, int或long。

其他回答

我不太明白你的问题。

我刚刚尝试了这一点,对于字节-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表示为字节值。MAX_VALUE(127)你必须使用不同的整型,如short, int或long。

在Java中使用unsigned字节的完整指南:

Java中的无符号字节

(答案来源)


Java语言不提供任何类似unsigned关键字的东西。根据语言规范,一个字节表示−128 - 127之间的值。例如,如果将一个字节转换为int类型,Java将把第一位解释为符号并使用符号扩展。

也就是说,没有什么可以阻止您将一个字节简单地视为8位,并将这些位解释为0到255之间的值。只要记住,你不能把你的解释强加给别人的方法。如果一个方法接受一个字节,那么该方法接受−128到127之间的值,除非另有明确说明。

下面是一些有用的转换/操作,方便您使用:

从int到int的转换

// From int to unsigned byte
int i = 200;                    // some value between 0 and 255
byte b = (byte) i;              // 8 bits representing that value

// From unsigned byte to int
byte b = 123;                   // 8 bits representing a value between 0 and 255
int i = b & 0xFF;               // an int representing the same value

(或者,如果你使用的是Java 8+,使用Byte.toUnsignedInt。)

解析/格式化

最好的方法是使用上面的转换:

// Parse an unsigned byte
byte b = (byte) Integer.parseInt("200");

// Print an unsigned byte
System.out.println("Value of my unsigned byte: " + (b & 0xFF));

算法

2补表示“只适用于”加法、减法和乘法:

// two unsigned bytes
byte b1 = (byte) 200;
byte b2 = (byte) 15;

byte sum  = (byte) (b1 + b2);  // 215
byte diff = (byte) (b1 - b2);  // 185
byte prod = (byte) (b2 * b2);  // 225

除法需要手动转换操作数:

byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));

由于Java中的限制,无符号字节在当前的数据类型格式中几乎是不可能的。你可以为你要实现的东西使用其他语言的其他库,然后你可以使用JNI调用它们。

我认为其他答案已经涵盖了内存表示,您如何处理这些取决于您计划如何使用它的上下文。我要补充的是,Java 8增加了一些处理无符号类型的支持。在这种情况下,您可以使用Byte.toUnsignedInt

int unsignedInt = Byte.toUnsignedInt(myByte);

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

由于原语是有符号的,Java编译器将阻止您为字节分配大于+127的值(或小于-128的值)。然而,没有什么可以阻止你向下转换一个int型(或short型)来实现这一点:

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"
}