为啥字节在java中不取0xff?
Posted
技术标签:
【中文标题】为啥字节在java中不取0xff?【英文标题】:Why will byte not take 0xff in java?为什么字节在java中不取0xff? 【发布时间】:2013-09-15 13:21:43 【问题描述】:为什么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 中查看 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,并且常量表达式的值可以在变量的类型中表示,则可以使用缩小原语转换。”
如您所见,这并不只是适用于文字。它适用于所有(编译时)常量表达式!
跟进
我阅读了声称
0xff
是255
的答案,这是怎么回事?不是1111 1111
,是什么造就了0xff
、-128
或255
或与此相关的任何东西?
文字0xff
是一个int
类型的整数文字。文字0xff
的int
值实际上是二进制的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 字母
L
或l
(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:无效的起始字节