为什么byte不会在java中占用0xff?
为什么java编译器不允许我将0xff
放入一个byte
, 0xff
是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语言允许在没有强制转换的情况下进行赋值。 文字的值从int
到byte
隐式缩小。
JLS§5.2中描述了这一点,它定义了可以在赋值中执行的转换:
“如果变量的类型是byte,short或char,则可以使用缩小的原始转换,并且常量表达式的值可以在变量的类型中表示。”
正如您所看到的,这不仅适用于文字。 它适用于所有(编译时)常量表达式!
跟进
我看到答案声称
0xff
是255
,怎么回事? 是不是1111 1111
,是什么让0xff
,-128
或255
或其他任何事情?
文字0xff
是int
类型的整数文字 。 文字0xff
的int
值实际上是二进制的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字母
L
或l
(ell),则为int
类型;否则为int
( §4.2.1 )类型。”
0xff
是数字的hex表示 。 换句话说,数字是16。
f = 15
hex。
该值等于
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。