首页 > 解决方案 > Java一元提升、左移运算符和short

问题描述

JLS §5.6.1说:

一些运算符将一元数字提升应用于单个操作数,该操作数必须产生一个数字类型的值:
...
如果操作数是编译时类型 byte、short 或 char,则将其提升为 int 类型的值扩大的原语转换
...
在以下情况下对表达式执行一元数值提升:
...
每个操作数,分别是移位运算符 <<、>> 或 >>>

这就解释了为什么这个程序无法编译:

public class xx {
    public short twice(short x) {
        return x << 1;
    }
}

出现此错误:

$ javac xx.java
xx.java:3: error: incompatible types: possible lossy conversion from int to short
        return x << 1;
                 ^
1 error

好的。那么为什么这个程序编译成功呢?

public class xx {
    public short two() {
        return (short)1 << 1;
    }
}

表达式不(short)1符合“编译时类型字节、短或字符”的条件吗?

这是我正在使用的:

$ java -version
openjdk version "1.8.0_282"
OpenJDK Runtime Environment (build 1.8.0_282-bre_2021_01_20_16_37-b00)
OpenJDK 64-Bit Server VM (build 25.282-b00, mixed mode)

标签: javajavacjls

解决方案


演员在这里是红鲱鱼;没有它,代码编译相同。重要的是表达式1 << 1是一个常量表达式。所以说JLS(§5.2 强调我的):

赋值上下文允许将表达式的值(第 15.26 节)赋值给变量;表达式的类型必须转换为变量的类型。[...] 如果表达式是类型为 、、 或的常量表达式(第 15.28 节) :如果变量的类型是、或,并且常量表达式的值是可表示的,则可以使用缩小原始转换在变量的类型中。byteshortcharintbyteshortchar

请注意,您的表达式出现在return语句中,而不是变量赋值中,但§14.17告诉我们该表达式是赋值上下文,因此上面引用的 §5.2 适用。

所以你有一个类型的赋值上下文short,并且在那个上下文中你有一个常量表达式1 << 1,它产生值2,它确实可以在类型中表示short。所以这就是它编译的原因。


推荐阅读