如果在移位运算符中使用强制转换运算符怎么办

问题描述

JLS

shift表达式的类型是左手的提升类型 操作数。

如果左侧操作数的提升类型为int,则仅 右侧操作数的五个最低位用作移位 距离。好像右手操作数受到了 掩码值为0x1f的按位逻辑AND运算符&(§15.22.1) (0b11111)。因此,实际使用的换档距离始终在 范围为0到31(含)。

如果左侧操作数的提升类型很长,则仅 右操作数的最低6位用作移位 距离。好像右手操作数受到了 掩码值为0x3f的按位逻辑AND运算符&(§15.22.1) (0b111111)。因此,实际使用的移动距离始终为 范围为0到63(含)。

因此,如果我使用(byte)100<<100(short)100<<100之类的转换运算符显式地创建一个字节和一个短操作数,那么正确的操作数的可用位是什么?

编辑:如果操作数已经使用强制转换运算符转换为其他(较小的)类型,则该操作数是否会进行数值提升(一元/二进制)?如果是这种情况,您将如何解释具有字节变量b1 = (byte)(b2 + b3)的表达式,因为在进行强制转换之后,字节结果可能会按照数字提升转换为int?

解决方法

Java 8 JLS also states in §5.6.1

5.6.1。一元数值促销

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

...

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

...

因此,如果我们采用以下表达式:

int i = ...
short s = (short) i << 2;

将导致编译器错误:

Main.java:4: error: incompatible types: possible lossy conversion from int to short
short s = (short) i << 2;

Ideone demo

这是由于强制转换绑定到shift的第一个参数,而不是整个表达式。这是带有显式括号的整个表达式:

short s = ((byte) i) << 2;

int i = ...;
int j = (short) i << 2;

将成功编译。

Ideone demo

因此,< int的有效位与int5位)相同,因为它们会自动上载到int

如果将整个表达式的结果强制转换为,例如shortshort s = (short) (i << 2),那么编译器中就不会发生自动操作。但是Bohemian's answer给出了逻辑运算符,确定了右运算符的哪些位将有效地影响运算符之后的值。演员。


在较新的JLS版本中,该部分已改写。例如,在Java 14 JLS,§5.6中我们发现(为简洁起见,本节已缩短,我建议阅读整个段落以获取完整的上下文):

5.6。数值上下文

数值上下文适用于算术运算符,数组创建和访问表达式,条件表达式以及切换表达式的结果表达式的操作数。

如果表达式是下列之一,则表达式将出现在数字算术上下文中:

...

  • 移位运算符<<>>>>>的操作数(第15.19节)。这些移位运算符的操作数将被单独对待而不是作为一个整体来对待。 long移位距离(右操作数)不会促进将值(左操作数)移位到long

...

数字提升确定数字上下文中所有表达式的提升类型。选择提升类型,以便可以将每个表达式转换为提升类型,并且在算术运算的情况下,将为提升类型的值定义该运算。在数字上下文中,表达式的顺序对于数字提升并不重要。规则如下:

...

  1. 接下来,根据以下规则,将扩展原语转换(第5.1.2节)和缩小原语转换(第5.1.3节)应用于某些表达式:

    ...

    • 否则,所有表达式都不属于doublefloatlong类型。在这种情况下,上下文的类型决定了如何选择提升的类型。

      在数值算术上下文或数值数组上下文中,提升后的类型为int,所有非int类型的表达式都将原语转换为int

      在数字选择上下文中,适用以下规则:

      ...

      • 否则,升级后的类型为int,所有非int类型的表达式都将原语转换为int

      ...

,

最大可用移位距离的位数由log 2 n给出,其中n是用于表示左手类型的值的位数。

byte有8位。 log 2 8是3。因此,仅使用最右边的3位,给出的移位值为0-7。

short具有16位。 log 2 16是4。所以仅使用最右边的4位,给出的移位值为0-15。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...