为什么字节和短分区在Java中导致int?

lex*_*ore 3 java integer division integer-division

在Java中,如果我们划分bytes,shorts或ints,我们总是得到一个int.如果其中一个操作数是long,我们就会得到long.

我的问题是 - 为什么byteshort除法不产生byteshort?为什么总是int

显然我不是在寻找"因为JLS这么说"的答案,我在Java语言中询问这个设计决策的技术原理.

考虑以下代码示例:

    byte byteA = 127;
    byte byteB = -128;
    short shortA = 32767;
    short shortB = -32768;
    int intA = 2147483647;
    int intB = - -2147483648;
    long longA = 9223372036854775807L;
    long longB = -9223372036854775808L;


    int byteAByteB = byteA/byteB;
    int byteAShortB = byteA/shortB;
    int byteAIntB = byteA/intB;
    long byteALongB = byteA/longB;

    int shortAByteB = shortA/byteB;
    int shortAShortB = shortA/shortB;
    int shortAIntB = shortA/intB;
    long shortALongB = shortA/longB;

    int intAByteB = intA/byteB;
    int intAShortB = intA/shortB;
    int intAIntB = intA/intB;
    long intALongB = intA/longB;

    long longAByteB = longA/byteB;
    long longAShortB = longA/shortB;
    long longAIntB = longA/intB;
    long longALongB = longA/longB;
Run Code Online (Sandbox Code Playgroud)

byteA除以byteB一个字节,除以不能是什么呢?
那么为什么必须byteAByteB是一个int?为什么不能shortALongBshort
为什么intALongB必须如此long,结果总是适合int,不是吗?

更新

正如@Eran指出的那样,(byte)-128/(byte)-1结果128不适合byte.但为什么不short呢?

更新2

接下来,正如@Eran指出的那样(再次),(int) -2147483648 / (int) -1也不适合,int但结果int却不是long.

Era*_*ran 6

byteA除以byteB不能只是一个字节,可以吗?

它可以不是字节:

byteA = -128;
byteB = -1;
int div = byteA/byteB; // == 128, not a byte
Run Code Online (Sandbox Code Playgroud)


Jea*_*nès 5

主要原因是机器通常只具有针对其本机整数类型(和浮点数)的加法指令。这就是为什么对于许多语言来说,算术表达式中最少使用的类型是int(通常是在某种程度上对应于基本机器整数类型的类型)。

例如,i386 规范说:

ADD 对两个操作数(DEST 和 SRC)执行整数加法。加法的结果分配给第一个操作数 (DEST),并相应地设置标志。将立即数字节添加到字或双字操作数时,立即值将符号扩展为字或双字操作数的大小。

这意味着在内部任何字节值都会扩展为整数(或类似的值)。毕竟这是合理的,因为处理器是 32/64 位,然后以这些大小执行任何算术。如果可以以字节为单位进行算术,那么通常认为这没有用。

JVM 规范说(为了补充)你有:iadd, ladd, fadd, dadd. 这只是反映了底层机器通常这样做的事实。任何其他选择都是可能的,但可能会以性能下降为代价。