为啥字节在java中不取0xff?

Posted

技术标签:

【中文标题】为啥字节在java中不取0xff?【英文标题】:Why will byte not take 0xff in java?为什么字节在java中不取0xff? 【发布时间】:2013-09-15 13:21:43 【问题描述】:

为什么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 中查看 primitives 的文档 在 Java 中,一个字节被限制为 -128 到 127,因为它被认为是一个有符号的原语。您不能将整数转换为字节,因为基元只能在层次结构中向上移动,而不能向下移动。 【参考方案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,并且常量表达式的值可以在变量的类型中表示,则可以使用缩小原语转换。”

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


跟进

我阅读了声称0xff255 的答案,这是怎么回事?不是1111 1111,是什么造就了0xff-128255 或与此相关的任何东西?

文字0xff 是一个int 类型的整数文字。文字0xffint 值实际上是二进制的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 所说:

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

【讨论】:

【参考方案2】:

0xff 是一个数字的hexadecimal representation。换句话说,这个数字是以 16 为底的。

f = 15 十六进制。

值等于

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

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

您发布的两个示例都无法编译,因为它们都不适合byte-128 to 127 值范围。您可以阅读原始类型值范围here。

这会起作用

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

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

【讨论】:

【参考方案3】:

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

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

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

这个输出:

ff

【讨论】:

【参考方案4】:

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

【讨论】:

(-128 to 127) 出现在您的短语的错误位置。这些实际上是有符号的值。

以上是关于为啥字节在java中不取0xff?的主要内容,如果未能解决你的问题,请参考以下文章

错误UnicodeDecodeError:'utf-8'编解码器无法解码位置0的字节0xff:无效的起始字节

无符号短字节数组

int的高位字节和低位字节

psql 导入错误:无效行号:e 错误:编码“UTF8”的字节序列无效:0xff

快速访问内置类型的每一位字节

Objectvie-C 两个字节 转换成整数