java中的按位运算符只用于整数和长整数?

时间:2013-12-13 23:15:42

标签: java bit-manipulation bitwise-operators

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

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

Eclipse希望在按位补码的行中使用强制转换为字节。它说:“类型不匹配:无法从int转换为字节”。我还尝试了其他按位操作和其他整数类型。它与简短和char相同。只有long和整数才能使用按位运算。

这是否有原因?

2 个答案:

答案 0 :(得分:12)

Java中的一元(例如~)和二元运算符分别将其操作数设置为"unary numeric promotion" (JLS, Section 5.6.1)"binary numeric promotion" (JLS, Section 5.6.2),用于“将事物推广到至少int的奇特术语”第一”。

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

  

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

  

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

(二进制数字促销类似,在两个操作数上运行。)

因此,即使bbyte~b也是int,因为b的值已提升为int首先。

解决方案:将其投回byte

b = (byte) (~b);

为什么,Java?

这就留下了问题,为什么?对于我能找到的运算符来说,在byteshortchar上运行的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

但是,对于intlong s floatdouble版本,我只能find instructions for XOR(以及其他一元和二元运算符)在适当的情况下存在于其他运营商。)

因此,Java必须执行这些促销,因为没有用于在byteshortchar s上执行这些操作的字节码指令。

为什么不,JVM?

这提出了另一个问题:为什么JVM不支持这样的字节码指令?答案似乎是,“因为在一个字节的指令集中对它们进行编码的次数太多了。”根据{{​​3}},

  

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

(强调我的)

总之,JVM的单字节码指令集排除了bytecharshort上大多数操作的字节码指令,需要一元数字提升和二进制数字推广。

答案 1 :(得分:3)

是的,小于int的类型在用作大多数运营商的操作数时会进行促销。它们首先被有效地转换为int。因此,在上面的代码中,结果的类型为int。有关详细信息,请参阅JLS的this section

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