我在下一个代码片段中遇到了对原语提升的误解。
byte a = 2;
int b = a >> 4L;
我会期待什么
long b = (int)a >> 4L;
long b = a >> 4L;
int b = a >> 4L;
int >> long
将升级到更大的数据类型(long
),并且不会使用生成的int
类型进行编译。
我收到了什么
它编译得很好为什么
JLS在这里不会"升级到更大的数据类型",因为它不会对移位运算符执行二进制数字升级。JLS第15.19节对此进行了说明。
对每个操作数分别执行一元数字提升(§5.6.)。(二进制数字提升(§5.6.2)不是对操作数执行而。)
一元数字提升将字节a
提升为int
。文字4L
没有改变,但它只需要是一个积分类型。
如果移位运算符的每个操作数的类型在一元数字提升后不是基元积分类型,则是编译时错误。
然后,对于移位,仅使用最低5个有效位来移位int
。
如果左侧操作数的提升类型为int,则只有右侧操作数的五个最低阶位用作移位距离。就好像右侧操作数受到按位逻辑AND运算符&(§15.22.1),掩码值为0x1f(0b11111)。因此,实际使用的偏移距离总是在0到31(包括0到31)的范围内。
运算符的结果是int
,而不是long
,因此可以在没有编译器错误的情况下将其分配给int
。
移位表达式的类型是左侧操作数的提升类型。
由JLS:
移位表达式的类型是左侧操作数的提升类型。
移位运算符的右侧操作数对表达式的类型没有任何影响。与+
这样的运算符不同,右边的较大类型并不意味着结果可以更大或更小。