【问题标题】:Bitwise operators in java only for integer and long?java中的位运算符仅用于整数和长整数?
【发布时间】:2013-12-13 23:15:41
【问题描述】:

我在 Eclipse 中编写了以下代码:

byte b = 10;
/* some other operations */
b = ~b;

Eclipse 想要在按位补码的行中强制转换为字节。它说:“类型不匹配:无法从 int 转换为 byte”。我还尝试了其他按位运算和其他整数类型。它与short 和char 相同。只有 long 和 integer 可以使用按位运算。

这是有原因的吗?

【问题讨论】:

  • 可能是因为计算机必须对至少 32 位长的整个寄存器执行操作?
  • 是的!这可能是原因。

标签: java bit-manipulation bitwise-operators


【解决方案1】:

Java 中的一元(如~)和二元运算符分别将它们的操作数置于"unary numeric promotion" (JLS, Section 5.6.1)"binary numeric promotion" (JLS, Section 5.6.2) 中,即“将事物至少提升到int first”的花哨术语。

具体来说,对于一元数字提升,引用上面链接的 JLS 部分:

一些运算符将一元数字提升应用于单个操作数,该操作数必须产生一个数字类型的值:

...如果操作数是编译时类型 byte、short 或 char,则通过扩展原语转换(第 5.1.2 节)将其提升为 int 类型的值。

(二进制数值提升类似,对两个操作数都进行操作。)

所以,即使bbyte~b 也是int,因为b 的值首先被提升为int

解决方案:将其转换回byte

b = (byte) (~b);

为什么,Java?

这就留下了一个问题,为什么?对于我能找到的操作员来说,在bytes、shorts 和chars 上操作的 JVM 字节码指令似乎根本不存在。例如,您使用的一元按位补码运算符 (~) is implemented as an "XOR" operation with -1 (all bits set)。从那个链接:

tempSpock &= ~mask;

变成

25 iload_2 // Push local variable 2 (mask).
26 iconst_m1 // Push -1.
27 ixor // Bitwise EXCLUSIVE-OR top two ints: ~mask

但是,对于ints 和longs,我只能使用find instructions for XOR(以及其他一元和二元运算符)(floatdouble 版本适用于其他运算符)。

因此,Java 必须执行这些提升,因为没有字节码指令可以在 bytes、shorts 或 chars 上执行这些操作。

为什么不呢,JVM?

这就引出了另一个问题:为什么 JVM 不支持这样的字节码指令?答案似乎是,“因为在一个字节的指令集中编码它们的数量太多了。”根据JVM Specification, Section 2.11.1

鉴于 Java 虚拟机的单字节操作码大小,将类型编码为操作码会对其指令集的设计造成压力。如果每个类型化的指令都支持 Java 虚拟机的所有运行时数据类型,那么指令的数量将超过一个字节可以表示的数量。相反,Java 虚拟机的指令集为某些操作提供了较低级别的类型支持。换句话说,指令集故意不是正交的。可以根据需要使用单独的指令在不受支持和支持的数据类型之间进行转换。

(强调我的)

总之,JVM 的单字节码指令集排除了bytes、chars 和shorts 上大多数操作的字节码指令,因此需要一元数字提升和二进制数字提升。

【讨论】:

  • 你的字节码参数是无稽之谈。如果由语言指定,编译器可以很好地添加强制转换。举个例子,看看+=是如何在short上定义的。
【解决方案2】:

是的,小于int 的类型在用作大多数运算符的操作数时会进行提升。它们首先被有效地转换为int。因此,在您上面的代码中,结果的类型是int。详情请参阅 JLS 的this section

至于为什么Java 这样做,我不确定。但一个合理的原因是 C 做到了这一点,并且保持熟悉的语义可能是语言设计的目标。

【讨论】:

  • 能否提供一个参考,说明此行为在 C 中的定义位置?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 2012-09-19
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
相关资源
最近更新 更多