Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么字节和短除法在Java中会导致int?_Java_Integer_Division_Integer Division - Fatal编程技术网

为什么字节和短除法在Java中会导致int?

为什么字节和短除法在Java中会导致int?,java,integer,division,integer-division,Java,Integer,Division,Integer Division,在Java中,如果我们将bytes、shorts或ints分开,我们总是得到int。如果其中一个操作数是long,我们将得到long 我的问题是,byte或short除法为什么不产生byte或short?为什么总是int 显然,我不是在寻找“因为JLS这么说”的答案,我是在问Java语言中这个设计决策的技术原理 考虑以下代码示例: byte byteA = 127; byte byteB = -128; short shortA = 32767; short sh

在Java中,如果我们将
byte
s、
short
s或
int
s分开,我们总是得到
int
。如果其中一个操作数是
long
,我们将得到
long

我的问题是,
byte
short
除法为什么不产生
byte
short
?为什么总是
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;
byteA
除以
byteB
只能是一个字节,不是吗?
那么为什么
byteAByteB
必须是
int
?为什么
shortALongB
不能
short

为什么
intALongB
必须是
long
,结果总是符合
int
,不是吗

更新

正如@Eran所指出的,
(byte)-128/(byte)-1
导致
128
,这与
字节不匹配。那么为什么不缩短呢

更新2

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

byteA除以byteB只能是一个字节,对吗

它可以不是字节:

byteA = -128;
byteB = -1;
int div = byteA/byteB; // == 128, not a byte
我猜这是从C中得到的,可能是通过C++。< /P> 在这些语言中,如果一个或多个参数的类型比
int
的类型窄,则它们总是升级为
int
。这在计算表达式之前发生。由于生成的操作被转换为它所指定的类型,因此它经常被忽略,如果没有副作用,编译器可以很好地优化所有中间步骤

在Java中,虽然它不是太有害。(在C和C++中它可以让你知道:两个大的<代码>未签名的短s的乘法可以溢出<代码> int <代码>,其行为未定义。< /P>
请注意,如果其中一个参数大于
int
,则表达式的类型是参数类型中最大的。

我认为理由是简单规则产生的惊喜最少。结果总是两种类型中较宽的(最小值为
int
),它不依赖于操作

更好的方法可能是总是加宽
+
*
-
,除非显式(或隐式)缩小。i、 除非使用石膏,否则不要做溢流或下溢<例如,代码>/
可以始终是一个
double
long
操作,除非进行了铸造

但是C和Java并没有做到这一点

简而言之,它有一个简单的规则来处理这个问题,不管是好是坏



请参见此处的“我的rant”

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

例如,i386规范说明:

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

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


JVM规范说(作为补充)您有:
iadd
ladd
fadd
dadd
。这仅仅反映了一个事实,即底层机器通常表现出这样的行为。任何其他选择都是可能的,可能是以性能降低为代价的。

每当定义byte类型的变量时,无论您在其中键入什么,都应该是byte类型的变量

这意味着它只能是一个字节(-128到127)范围内的数字

但是,当您键入表达式时,例如,byteA/byteB,这与键入文字时不同。例如,数字127

这就是Java的本质-整数是用于整数的默认数据类型

默认情况下,在对表达式进行赋值时,Java会将其转换为默认数据类型(整数),尽管表达式的结果可能是字节的有效值

因此,当您定义一个字节并指定一个表达式作为该字节的值时,Java需要将其转换为整数:

int byteAByteB = byteA / byteB;
但是,您可以通过强制转换指定的表达式,从而放弃Java将其视为字节来解决这个问题

byte byteAByteB = (byte) (byteA / byteB);

这样,您告诉Java将其视为一个字节。(也可以用short等方式完成)

注意要点。那为什么不短一点呢?
一个字节也不短。。因为它没有无符号的概念。。128在其他支持unsigned的语言中仍然只是一个字节(
char
),请注意,
char
在Java中是一种16位无符号类型。很好。@lexicore你说得对,我的例子用Integer.MIN_值除以-1不起作用(因为操作数不会提升为long,所以会出现int溢出)。@Eran
-2147483648/-1
导致
-2147483648
。酷。打破了我今天的逻辑。你确定这是两种更广泛的类型吗?我的理解是