Java 将 int 转换为字节时出现奇怪的行为?

2022-08-31 08:19:54
int i =132;

byte b =(byte)i; System.out.println(b);

令人难以置信。为什么是输出?-124


答案 1

在 Java 中,an 是 32 位。A 为 8 。intbytebits

Java 中的大多数基元类型都是有符号的,和 、 、 和以二的补码编码。(类型为无符号,符号的概念不适用于 。)byteshortintlongcharboolean

在此数字方案中,最高有效位指定数字的符号。如果需要更多位,则最高有效位 (“MSB”) 只需复制到新的 MSB。

因此,如果您有byte :并且想要将其表示为(32位),则只需将1复制到左侧24次即可。25511111111int

现在,读取负二进制补码数的一种方法是从最低有效位开始,向左移动直到找到前一个1,然后反转每个位。得到的数字是该数字的正版本

例如:转到 = 。这就是 Java 将显示为值的内容。1111111100000001-1

您可能想做的是知道字节的无符号值。

您可以使用位掩码来实现此目的,该位掩码会删除除最不重要的 8 位之外的所有内容。(0xff)

所以:

byte signedByte = -1;
int unsignedByte = signedByte & (0xff);

System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);

将打印出来:"Signed: -1 Unsigned: 255"

这里到底发生了什么?

我们使用按位 AND 来屏蔽所有无关的符号位(最不重要的 8 位左侧的 1)。当一个int被转换成一个字节时,Java会砍掉最左边的24位

1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101

由于第 32 位现在是符号位而不是第 8 位(我们将符号位设置为 0,这是正数),因此 Java 将字节中的原始 8 位读取为正值。


答案 2

132in digits(以 10 为基数)以位为单位(以 2 为基数),Java 以 32 位为单位存储:1000_0100int

0000_0000_0000_0000_0000_0000_1000_0100

int 到 byte 的算法是左截断的;算法为二的补码(二的补码是如果最左边的位是,解释为负的一补(反转位)减去一);因此::System.out.println1System.out.println(int-to-byte())

  • interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(] left-truncate(0000_0000_0000_0000_0000_0000_1000_0100) [)))] )
  • =interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(]1000_0100 [)))] )
  • =interpret-as(negative(invert-bits(minus-one(1000_0100))))
  • =interpret-as(negative(invert-bits(1000_0011)))
  • =interpret-as(negative(0111_1100))
  • =解释为(否定(124))
  • =解释为(-124)
  • =-124 多田!!!

推荐