Java 二进制字面量 - byte 类型取值为 -128

10

自从SE 7以来,Java允许将值指定为二进制字面量。文档告诉我'byte'是一种可以容纳8位信息的类型,取值范围为-128到127。

现在我不知道为什么,但是如果我尝试将二进制字面量分配给Java中的一个字节,则只能定义7位而不是8位:

byte b = 0b000_0000;    //solves to the value 0
byte b1 = 0b000_0001;   //solves to the value 1
byte b3 = 0b000_0010;   //solves to the value 2
byte b4 = 0b000_0011;   //solves to the value 3     

一直到使用这 7 位时的最后几种可能性:

byte b5 = 0b011_1111;   //solves to the value 63
byte b6 = 0b111_1111;   //solves to the value 127

如果我想把它变成负数,我需要在前面加上一个负号,就像这样:

-

byte b7 = -0b111_1111;   //solves to the value -127

现在我的问题有一半是,他们告诉我使用8位数据类型,但我只使用7位来描述。另一半的问题是,除非使用32位int类型并可以定义所有32位(包括“符号指示位”),否则它们似乎不会作为二进制补码线程。

现在,当我搜索如何显示-128这个范围内的数字时,我被告知要按照以下方式操作,但没有进一步的解释:

byte b8 = 0b1111_1111_1111_1111_1111_1111_1000_0000;

我可以清楚地看到,最后8位(1000 0000)代表了在使用8位的二进制补码时的-128,但我并没有更深的困惑,因此我要问一下:

  • 上面的32位长数字不是一个32位(java)整数值吗?
  • 为什么我可以将32位值分配给8位(java)字节类型?

或者一般来说:为什么我必须这样分配?

任何关于这个问题的链接/信息都很好! 感谢您花时间阅读这篇文章以及提前提供的任何进一步信息。

敬礼 Jan


byte b8 = 0b1000_0000 这样写可以吗?另外请查阅二进制补码表示法。 - ratchet freak
很遗憾,byte b8 = 0b1000_0000是无效的。不过我失去了对这个问题的科学关注,但我认为这是预期的结果。有趣的是,这个问题从来没有得到完整的答案,需要检查如何设置奖励。 - JBA
1个回答

10
根据Java规范,

http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.1

所有声明(b,b1,...和b8)使用int字面量,即使它们适合一个字节。在Java中没有字节字面量,您只能使用int来初始化字节。

我进行了一些测试,byte neg128 = -0b1000_0000;可以正常工作。0b1000_0000是128,所以您只需要在它前面加上一个-符号。请注意,1 根本不是符号位(不要考虑8位字节,而要考虑转换为字节的32位整数)。因此,如果您想指定符号位,您需要编写所有32位,就像您已经演示的那样。

因此,byte b8 = 0b1000_0000;就像byte b8 = 128;一样是一个错误(+128无法适应一个字节)。您也可以使用强制转换来进行转换:

byte b = (byte) 0b1000_0000; 或者 byte b = (byte) 128;

cast关键字告诉编译器,你知道128不适合一个字节,并且该位模式将被重新解释为-128。


哦,我也有点惊讶,0b1000_0000在这种情况下没有自动进行符号扩展。 :-) - marcus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接