为什么字节在Java中不采用0xff?


问题内容

为什么Java编译器不会让我把0xffbyte0xff是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)投正在执行一个明确的收缩转换,去除整数的高位文字......给你的价值-127在你的byte变量。


实际上,第一个示例的情况要复杂得多。考虑一下:

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

在正常情况下,你不能分配intbyte没有投。但是,如果要分配的值是文字,并且文字值在目标类型的范围内,则Java语言允许进行赋值 而无需
强制转换。文字的值隐式地从缩小intbyte

JLS§5.2中对此进行了描述,它定义了可以在分配中执行的转换:

“如果变量的类型是字节,短或字符,并且常量表达式的值可以用变量的类型表示,则可以使用缩窄的原始转换。”

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


跟进

我阅读了声称0xff是的答案255,怎么回事?是不是1111 1111,是什么原因造成的0xff-128255与此无关的东西?

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

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

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

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