30

为什么 java 编译器不让我放入0xff,byte0xff8 位长,这只是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。

4

4 回答 4

56

Javabyte类型是一个 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

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

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

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

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


跟进

我读了声称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 )。”

于 2013-09-15T13:23:51.793 回答
15

0xff是数字的十六进制表示。换句话说,这个数字是以 16 为底的。

f = 15十六进制。

值等于

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

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

您发布的两个示例都不会编译,因为它们都不适合byte. 您可以在此处-128 to 127阅读有关原始类型值范围的信息。

这将起作用

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

和打印-1,因为一个字节缩小转换255-1

于 2013-09-15T13:26:09.837 回答
4

0xff是 255。虽然这确实适合 8 位无符号整数,但byte它是有符号的(-128 到 127)。缩小将删除高位并将 8 放入 8 中而不考虑符号。

于 2013-09-15T13:24:03.370 回答
4

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

因为 java 'byte' 类型是一个 8 位有符号整数值(从 -128 到 127),要将字节输出/打印为十六进制,您可以使用 Integer.toHexString('the original byte' & 0xFF) where ' & 0xFF ' 是一个位掩码,考虑到 Integer 使用 32bit int 而 byte 使用 8bit。

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

这输出:

ff
于 2013-09-15T13:35:49.230 回答