为什么byte不会在java中占用0xff?

为什么java编译器不允许我将0xff放入一个byte0xff是8位长,这只是byte数据类型的大小。

有人可以解释为什么1有效,为什么有2无效?

 class a { public static void main(String[] args) { // 1 :: results in error byte a = 0xff; System.out.printf("%x\n",a); //2 :: works fine byte a = (int)0xff System.out.printf("%x\n",a); } } 

编辑我读了答案声称0xff是255,怎么回事? 是不是1111 1111 ,是什么让0xff,-128或255或其他任何事情。 为什么它不仅仅将它视为1111 1111而不是该字节的8位为1。

Java byte类型是8位有符号整数类型,其值在-128+127范围内。 文字0xff表示+255 ,超出该范围。

在第一个示例中,您尝试将超出范围的值分配给一个byte 。 这是一个编译错误。

在第二个例子中, (byte)强制转换执行显式缩小转换,删除整数文字的高阶位…在byte变量中给出-127的值。


事实上,第一个例子的情况比这复杂一点。 考虑一下:

 byte a = 1; // OK int i = 1; byte b = i; // Compilation error byte c = (byte) i; // OK 

在正常情况下,如果没有强制转换,则无法将int分配给byte 。 但是,如果赋值的值是文字,并且文字值在目标类型的范围内,则Java语言允许在没有强制转换的情况下进行赋值。 文字的值从intbyte隐式缩小。

JLS§5.2中描述了这一点,它定义了可以在赋值中执行的转换:

“如果变量的类型是byte,short或char,则可以使用缩小的原始转换,并且常量表达式的值可以在变量的类型中表示。”

正如您所看到的,这不仅适用于文字。 它适用于所有(编译时)常量表达式!


跟进

我看到答案声称0xff255 ,怎么回事? 是不是1111 1111 ,是什么让0xff-128255或其他任何事情?

文字0xffint类型的整数文字 。 文字0xffint值实际上是二进制的0000 0000 0000 0000 0000 0000 1111 1111或十进制的+255。 相反,文字-1具有位模式1111 1111 1111 1111 1111 1111 1111 1111

为什么它不仅仅将它视为1111 1111而不是该字节的8位为1?

因为0xff是一个类型为int的整数文字。 它不是8位字面值,因为Java中不存在8位字面值。 正如JLS§3.10.1所说:

“如果整数文字后缀为ASCII字母Ll (ell),则为int类型;否则为int ( §4.2.1 )类型。”

0xff是数字的hex表示 。 换句话说,数字是16。

f = 15hex。

该值等于

 15 * 16^1 + 15 * 16^0 = 255 

这是一个整数文字 (使用4个字节),超出了byte的值范围。

您发布的两个示例中的任何一个都不会编译,因为它们都不适合byte-128 to 127的值范围。 您可以在此处阅读基本类型值范围。

这会奏效

 byte a = (byte)0xff; System.out.println(a); 

并打印-1 ,因为255的字节缩小转换为-1

首先,如果我尝试运行你的代码,那么2. case也不起作用。 您将0xff转换为原始数据类型int(具有32位)并希望将其存储在仅具有8位的“字节”中。 Java也将您的第一个案例视为int,导致同样的问题。

因为java’字节’类型是一个8位有符号整数值(从-128到127),要输出/打印字节为hex,你可以使用Integer.toHexString(’原始字节’和0xFF)其中’& 0xFF’是一个位掩码,考虑到Integer使用32位int,而byte使用8位。

  byte myByte = (byte)0xff; System.out.println(Integer.toHexString(myByte & 0xFF)); 

这输出:

 ff 

0xff为255.虽然这适合8位无符号整数,但byte有符号(-128到127)。 缩小将移除高位并且在不考虑符号的情况下将8适合8。