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

考虑以下代码:

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的类型不短?

从Java规范 :

5.6.2二进制数字促销

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

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

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

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

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

对于二进制操作,小整数类型被提升为int ,操作的结果为int


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

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

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

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

添加int和short的结果应该是什么?

两个短裤相乘的结果应该是什么? 结果通常适合int,但因为我们截断为short,所以大多数乘法都会无声地失败。 之后施放到int将无济于事。

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

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

短线可以保持-32,768至32,767的值。 那么这个结果会导致溢出:

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

所以你的问题就变成了:为什么添加两个整数不会返回多长? 两个整数的乘法应该是多少? 好久不过? 一个BigNumber来覆盖整数最小值的情况?

备选方案3:选择大多数人可能想要的东西

所以结果应该是:

  • int用于乘以两个short或任何int操作。
  • 短路如果加上或减去短路,将短路除以任何整数类型,乘以两个字节,……
  • 如果将一个字节向右移位,则为byte;如果向左移位,则为int。
  • 等等…

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

它只是一种与C / C ++一致的设计选择,在设计Java时它们是主导语言。

例如,可以实现i * j,以便从byte => short,short => int和int => long提升类型,这样可以避免溢出,但事实并非如此。 (在某些语言中确实如此)如果需要当前行为,可以使用Casting,但是一些位的丢失将是明确的。

类似地,可以从byte / short => float或int / long => double提示i / j。