【问题标题】:Why does 0b1111_1111 cause a compiler error "int cannot be converted to byte" but not 0b111_1111? [duplicate]为什么0b1111_1111会导致编译器错误“int无法转换为字节”而不是0b111_1111? [复制]
【发布时间】:2021-06-15 10:07:34
【问题描述】:
byte b = 0b1111_1111;
byte c = 0b111_1111;
byte d = 0b0111_1111;

第一行导致编译错误:不兼容的类型。我也试过0xFF和十进制,一样。谢谢。

我认为byte 的意思是不能大于 8 位的值。 0b1111_1111 为 8 位。

【问题讨论】:

  • 因为0b1111_1111 是不适合byte 的数字255。请注意,byte 是一个有符号的 8 位数字,范围从 -128 到 +127。
  • 您应该发布错误消息。另外你的描述是错误的。错误已经在第 1 行(变量 b)。您也可以在线测试:tutorialspoint.com/compile_java_online.php
  • 我认为字节的意思不能大于 8 位。 0b1111_1111 是 8 位。
  • @Tiina 是的,一个字节是 8 位。但是您使用的语法不允许您单独定义每个位。 Java 中的语法0b1111_1111; 仅表示以二进制形式写入的数字。最后byte b = 0b1111_1111;byte b = 255; 完全一样,只是你将数字声明为二进制。
  • Tiina 我认为误解是关于 0b。您将其视为您将值分配给(字节)的类型。但是编译器会看到文字并将其解释为 int。此后,它查看作业。您所要做的就是告诉编译器您的文字是一个字节:(byte) 0b1111_1111。或将 -1 写为二进制 int:0b1111_1111_1111_1111_1111_1111_1111_1111

标签: java


【解决方案1】:

Java 中的所有基本整数类型都是有符号的。确切地说,byteshortintlong 是有符号的大端二补整数。这意味着它们从 - 2n-1 运行到 2n-1 - 1 其中 n 是位数 - 8 代表一个字节(Java 中的Byte.SIZE ),因此范围是 -128 到 127。

您使用的数字始终是整数;数字文字总是如此。但是,整数实际上是十六进制的值0x000000FF。不能存储,因为它高于 127。但是,您可以进行显式转换;毕竟,您的值确实包含 8 位。

byte b = (byte) 0b1111_1111

有效,因为它只是忽略了值左侧的 24 位。现在,如果您打印它,您将得到 -1 作为值,尽管 0b1111_1111 表示 8 位二进制补码形式的 1。

如果你需要它来表示整数值 255 那么你需要执行以下小技巧:

int i = b & 0xFF;

实际上会执行以下操作:

  • 首先它将使用符号扩展将 b 转换为值 0xFFFFFFFF 作为整数,因为所有计算都默认为整数,它仍然认为 b 代表 -1。
  • 然后它对值0x000000FF(称为“掩码”)执行按位与运算,当然会得到相同的值0x000000FF,它代表255。

如果您认为这很麻烦,那么您是对的。 Java 应该使用无符号字节,但它决定只使用一种特定的有符号整数类型。也许有点过分热心,但仍然比 e.g. 有了很大的改进。在 C 中,整数格式太多了,而且每种格式在不同的机器上都可能以不同的方式表示。

【讨论】:

  • “大端”到底是什么意思?我很确定所有 jvm 实现都以机器字节顺序存储整数,不是吗?
  • @DietmarHöhmann 是的,但那将是 虚拟机字节顺序,这是大端序。至少这就是描述 VM 的方式,如何解释字节码是另一个主题。如果你描述一个字面值,那么它使用相同的顺序(尽管很有趣,小端机器对整数值使用相同的大端描述)。所有 IO 函数也默认使用 Big Endian(DataOutputStreamByteBuffer 等)。
  • 我明白了。所以类文件中的文字总是大端的,JIT 编译器可能(或可能不)将其转换为小端。查看有意义的 Java 源代码。谢谢你的解释!
猜你喜欢
  • 2017-07-30
  • 1970-01-01
  • 2016-05-13
  • 2011-06-09
  • 2015-10-01
  • 2017-10-30
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
相关资源
最近更新 更多