为什么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。
答案 0 :(得分:50)
Java byte
类型是8位有符号整数类型,其值在-128
到+127
范围内。文字0xff
代表+255
,超出了该范围。
在第一个示例中,您尝试将超出范围的值分配给byte
。这是编译错误。
在第二个示例中,(byte)
强制转换正在执行显式缩小转换,删除整数文字的高阶位...在-127
中为您提供值byte
变量。
事实上,第一个例子的情况比这复杂一点。考虑一下:
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,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。” < / p>
正如您所看到的,这不是只是适用于文字。它适用于所有(编译时)常量表达式!
<强>后续强>
我看到答案声称
0xff
是255
,怎么回事?是不是1111 1111
,是什么让0xff
,-128
或255
或其他任何事情发生?
文字0xff
是类型int
的整数文字。文字int
的{{1}}值实际上是二进制0xff
或十进制+255。相比之下,文字0000 0000 0000 0000 0000 0000 1111 1111
具有位模式-1
。
为什么不将它视为
1111 1111 1111 1111 1111 1111 1111 1111
而不是将该字节的8位视为1?
因为1111 1111
是类型为0xff
的整数文字。它不是8位字面值,因为Java中不存在8位字面值。正如JLS §3.10.1所说:
“整数文字的类型为
int
,如果后缀为ASCII字母long
或L
(ell);否则为{{1}类型}(§4.2.1)。“
答案 1 :(得分:15)
0xff
是一个hexadecimal representation的数字。换句话说,这个数字是16的基数。
f = 15
。
该值等于
15 * 16^1 + 15 * 16^0 = 255
这是integer literal(使用4个字节),超出byte
的值范围。
您发布的两个示例中的任何一个都不会编译为byte
的{{1}}值范围。您可以阅读有关基本类型值范围here的信息。
这将有效
-128 to 127
并打印byte a = (byte)0xff;
System.out.println(a);
,因为-1
转换的字节缩小为255
。
答案 2 :(得分:4)
0xff
为255.虽然这确实适合8位无符号整数,但byte
已签名(-128到127)。变窄将移除高位并将8变为8而不考虑符号。
答案 3 :(得分:4)
首先,如果我尝试运行您的代码,那么2.案例也不起作用。您将0xff转换为原始数据类型int(具有32位)并希望将其存储在&#39;字节中。只有8位。 Java也将你的第一个案例视为int,导致同样的问题。
因为java&#39;字节&#39; type是一个8位有符号整数值(从-128到127),以十六进制形式输出/打印字节,你可以使用Integer.toHexString(&#39;原始字节&#39;&amp; 0xFF)其中&# 39; &安培; 0xFF&#39;是一个位掩码,考虑到Integer使用32位int,而byte使用8位。
byte myByte = (byte)0xff;
System.out.println(Integer.toHexString(myByte & 0xFF));
输出:
ff