[英]Bitwise operators in java only for integer and long?
我在Eclipse中编写了以下代码:
byte b = 10;
/* some other operations */
b = ~b;
Eclipse希望在按位补码的行中使用强制转换为字节。 它说:“类型不匹配:无法从int转换为字节”。 我还尝试了其他按位操作和其他整数类型。 它与简短和char相同。 只有long和整数才能使用按位运算。
是否有一个原因?
Java中的一元(例如~
)和二元运算符分别使其操作数为“一元数字推广”(JLS,第5.6.1节)和“二进制数字推广”(JLS,第5.6.2节) ,用于“推广”的精彩术语事情至少int
第一”。
具体来说,对于一元数字促销,引用上面链接的JLS部分:
某些运算符将单一数字提升应用于单个操作数,该操作数必须生成数值类型的值:
和
...如果操作数是编译时类型byte,short或char,则通过扩展原语转换(第5.1.2节)将其提升为int类型的值。
(二进制数字提升类似,在两个操作数上运行。)
因此,即使b
是一个byte
, ~b
也是一个int
,因为b
的值首先被提升为int
。
解决方案:将其转换回一个byte
:
b = (byte) (~b);
为什么,Java?
这就留下了问题,为什么? 对于我能找到的运算符来说,用于操作byte
s, short
s和char
的JVM字节码指令根本就不存在。 例如,您正在使用的一元按位补码运算符(〜) 被实现为带有-1
的“XOR”运算(所有位都设置) 。 从该链接:
tempSpock &= ~mask;
变
25 iload_2 // Push local variable 2 (mask).
26 iconst_m1 // Push -1.
27 ixor // Bitwise EXCLUSIVE-OR top two ints: ~mask
但是,我只能找到针对int
和long
的XOR (以及其他一元和二元运算符)的指令 (在适当的情况下,其他运算符存在float
和double
版本)。
因此,Java必须执行这些促销,因为没有用于在byte
s, short
s或char
上执行这些操作的byte
码指令。
为什么不,JVM?
这带来了另一个问题:为什么JVM不支持这样的字节码指令? 答案似乎是,“因为在一个字节的指令集中对它们进行编码的次数太多了。” 根据JVM规范,第2.11.1节 ,
鉴于Java虚拟机的单字节操作码大小 ,编码类型到操作码会对其指令集的设计造成压力。 如果每个类型化指令都支持所有Java虚拟机的运行时数据类型, 则会有更多指令,而不是在一个字节中表示 。 相反,Java虚拟机的指令集为某些操作提供了降低级别的类型支持。 换句话说,指令集故意不正交。 可以根据需要使用单独的指令在不支持的数据类型和支持的数据类型之间进行转换。
(强调我的)
总之,JVM的单字节码指令集排除了byte
s, char
和short
上大多数操作的字节码指令,需要一元数字提升和二进制数字提升。
是的,小于int
类型在用作大多数运营商的操作数时会进行升级 。 它们首先被有效地转换为int
。 因此,在上面的代码中,结果的类型是int
。 有关完整详细信息,请参阅JLS的此部分 。
至于为什么 Java这样做,我不确定。 但有一个合理的原因是C做到了这一点,维护熟悉的语义可能是语言设计的目标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.