为什么 Java 中短整型除法的结果类型不是短整数?

2022-09-04 01:28:45

请考虑以下代码:

public class ShortDivision {
    public static void main(String[] args) {
        short i = 2;
        short j = 1;
        short k = i/j;
    }
}

编译此错误会产生错误

ShortDivision.java:5: possible loss of precision
found   : int
required: short
        short k = i/j;

因为表达式 i/j 的类型显然是 int,因此必须转换为 short。

为什么类型不短?i/j


答案 1

来自 Java 规范

5.6.2 二进制数字提升

当运算符将二进制数字提升应用于一对操作数(每个操作数必须表示一个数字类型的值)时,以下规则将按顺序应用,使用加宽转换 (§5.1.2) 根据需要转换操作数:

如果任一操作数的类型为双精度型,则另一个操作数将转换为双精度型。

否则,如果任一操作数的类型为 float,则另一个操作数将转换为 float。

否则,如果任一操作数的类型为 long,则另一个操作数将转换为 long。

否则,两个操作数都将转换为 int 类型。

对于二进制运算,小整数类型被提升为,运算的结果是 。intint


编辑:为什么会这样?简短的答案是Java从C复制了这种行为。更长的答案可能与所有现代机器都至少执行32位本机计算的事实有关,并且某些机器实际上可能更难执行8位和16位操作。

另请参见:C# 中的 OR-ing 字节给出 int


答案 2

关于动机:让我们想象一下这种行为的替代方案,看看为什么它们不起作用:

备选方案1:结果应始终与输入相同。

添加整型和短整型的结果应该是什么?

将两个短路相乘的结果应该是什么?一般来说,结果将适合int,但是由于我们截断为短整,因此大多数乘法将静默地失败。之后强制转换为 int 将无济于事。

备选方案 2:结果应始终是可以表示所有可能输出的最小类型。

如果返回类型是短整型,则答案并不总是可表示为短整型。

空头可以保存值 -32,768 到 32,767。然后这个结果将导致溢出:

short result = -32768 / -1; // 32768: not a short

所以你的问题变成了:为什么添加两个int不返回很长?两个整数的乘法应该是什么?很长?一个 BigNumber 来涵盖平方整数最小值的情况?

备选方案3:选择大多数人可能大部分时间都想要的东西

所以结果应该是:

  • int 用于将两个短整型或任何 int 运算相乘。
  • 如果添加或减去短整线,将短整除以任何整数类型,乘以两个字节,则为 short,...
  • 如果位将字节移位到右侧,则为 int 如果位向左移动。
  • 等。。。

如果没有基本的逻辑,记住所有特殊情况将是困难的。更简单地说:整数运算的结果始终是整数。