我们可以在Java中创建无符号字节

dln*_*dln 174 java unsigned

我试图转换无符号的有符号字节.问题是我收到的数据是无符号的,Java不支持无符号字节,因此当它读取数据时,它将其视为已签名.

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

public static int unsignedToBytes(byte a)
{
    int b = a & 0xFF;
    return b;
}
Run Code Online (Sandbox Code Playgroud)

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

Ada*_*ski 187

基元在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"
}
Run Code Online (Sandbox Code Playgroud)

  • 访问具有潜在负数的数组并非无关紧要. (54认同)
  • 对于许多操作而言,它没有任何区别,但是对于某些操作它确实如此.无论哪种方式,您都可以使用无符号字节,或使用无符号字符. (5认同)
  • 这与这个问题有点无关.由于他提到他需要将它传递给只接受字节参数的函数,所以天气并不重要,我们将其解释为独角兽的字节表示.Java将始终将其视为带符号的数字,当此函数将参数用作索引时,这可能会出现问题.然而,为了公平起见,我还低估了其他前两个答案,因为他们也没有回答这个问题. (5认同)
  • @Stefan--我的意思是它们如何在线上表现无关紧要. (3认同)
  • @Stefan +1给你.如果您使用字节访问256个元素的数组,则绝对相关.这是一个很好的例子来说明为什么每个人都应该在转向Java或C#之前开始学习C和C++ (2认同)
  • @Adamski,是的,但是如果你执行 `arr[someByte]` ,那么 `someByte` 将自动提升为带有 [sign 扩展名](https://en.wikipedia.org/wiki/Sign_extension) 的 int 。因此,虽然您可以按照自己想要的方式解释 8 位,但*Java* 作为一种语言,会将其解释为*有符号值*。 (2认同)

Gui*_*ume 103

我不确定我理解你的问题.

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

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

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

这是你想要做的吗?

Java不允许将244表示为byte值,就像C一样.要表达上面的正整数Byte.MAX_VALUE(127),您必须使用其他整数类型,例如short,intlong.

  • 为什么你接受这个作为正确的答案?它所做的一切与您在问题中提到的方法完全相同 - 将字节转换为无符号整数. (92认同)
  • 它也可以被称为byteToUnsigned (3认同)

aio*_*obe 41

Java语言不提供unsigned关键字之类的东西.byte根据语言规范,A 表示-128-127之间的值.例如,如果a byte转换为intJava,则将第一位解释为符号并使用符号扩展名.

话虽这么说,没有什么可以阻止你byte简单地查看8位并将这些位解释为介于0和255之间的值.请记住,没有什么可以强制你对别人的方法进行解释.如果方法接受a byte,则该方法接受介于-128和127之间的值,除非另有明确说明.

为方便起见,这里有一些有用的转换/操作:

来自int的转换

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

// 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
Run Code Online (Sandbox Code Playgroud)

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

解析/格式化

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

// Parse an unsigned byte
byte b = (byte) Integer.parseInt("200");
Run Code Online (Sandbox Code Playgroud)

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

算术

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
Run Code Online (Sandbox Code Playgroud)

部门需要手动转换操作数:

byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));
Run Code Online (Sandbox Code Playgroud)

  • 简而言之:[你错了](http://stackoverflow.com/questions/11671908/can-the-char-type-be-categorized-as-a-integer). (24认同)

Pet*_*ego 34

Java中没有原始的无符号字节.通常的做法是将其转换为更大的类型:

int anUnsignedByte = (int) aSignedByte & 0xff;
Run Code Online (Sandbox Code Playgroud)


mko*_*bit 20

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

int unsignedInt = Byte.toUnsignedInt(myByte);
Run Code Online (Sandbox Code Playgroud)


小智 5

附注,如果你想打印出来,你可以说

byte b = 255;
System.out.println((b < 0 ? 256 + b : b));
Run Code Online (Sandbox Code Playgroud)

  • 为什么这么复杂?`println(b &amp; 0xff)` 就足够了 (6认同)