Java:为什么收到错误消息“类型不匹配:无法将int转换为字节”

Java:为什么收到错误消息“类型不匹配:无法将int转换为字节”

Java: why do I receive the error message “Type mismatch: cannot convert int to byte”

如果声明类型为byte或short的变量并尝试对其进行算术运算,则会收到错误"类型不匹配:无法将int转换为short"(或相应的"类型不匹配:无法将int转换为byte")。

1
2
3
byte a = 23;
byte b = 34;
byte c = a + b;

在此示例中,编译错误在第三行。


尽管算术运算符被定义为可以对任何数字类型进行运算,但是根据Java语言规范(5.6.2二进制数字提升),字节和short类型的操作数在被传递给运算符之前会自动提升为int。

要对byte或short类型的变量执行算术运算,必须将表达式用括号括起来(在括号内将以int类型进行运算),然后将结果转换回所需的类型。

1
2
3
byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

这是真正的Java专家的一个后续问题:为什么? byte和short类型是完美的数字类型。为什么Java不允许对这些类型进行直接算术运算? (答案不是"精度下降",因为没有明显的理由首先将其转换为int。)

更新:jrudolph建议此行为基于JVM中可用的操作,尤其是仅实现全字和双字运算符。因此,对于字节和短裤运算符,必??须将它们转换为int。


您的后续问题的答案在这里:

operands of type byte and short are automatically promoted to int before being handed to the operators

因此,在您的示例中,ab都先转换为int,然后再交给+运算符。将两个int加在一起的结果也是一个int。然后尝试将int分配给byte值会导致错误,因为可能会丢失精度。通过显式转换结果,您将告诉编译器"我知道我在做什么"。


我认为问题是,JVM仅支持两种类型的堆栈值:字大小和双字大小。

然后,他们可能决定只需要一个对堆栈上字长的整数进行运算的操作。因此,在字节码级别只有iadd,imul等(并且没有用于字节和短裤的运算符)。

因此,您将得到一个int值,这些操作是Java无法安全地转换回较小字节和short数据类型的结果。因此,它们迫使您强制将值缩小到字节/短。

但是最后您是对的:例如,此行为与int的行为不一致。您可以毫无疑问地添加两个整数,并且如果结果溢出也不会出错。


Java语言始终将算术运算符的参数提升为int,long,float或double。因此,使用以下表达式:

1
a + b

其中a和b是字节类型。这是以下内容的简写:

1
(int)a + (int)b

此表达式的类型为int。将int值分配给字节变量时,给出错误显然很有意义。

为什么要用这种方式定义语言?假设a为60而b为70,则a + b为-126-整数溢出。作为可能导致int的更复杂表达式的一部分,这可能会成为一个困难的错误。限制使用字节和数组存储的简短形式,文件格式/网络协议和拼图的常量。

JavaPolis 2007上有一个有趣的记录。JamesGosling给出了一个例子,说明无符号算术有多么复杂(以及为什么Java中没有它)。乔什·布洛赫(Josh Bloch)指出,他的例子在正常的有符号算术下也给出了错误的例子。对于可理解的算法,我们需要任意精度。


推荐阅读

    linux命令错误的是?

    linux命令错误的是?,系统,信息,异常,密码,工具,地址,网络,实时,状态,数据,Lin

    linux显示错误命令?

    linux显示错误命令?,信息,系统,电脑,状态,时间,环境,命令,搜狐,密码,异常,虚

    linux退出错误命令的?

    linux退出错误命令的?,系统,电脑,环境,命令,位置,管理,工具,设备,终端,进程,L

    linux变量释放命令?

    linux变量释放命令?,系统,环境,名称,工具,官网,简介,变量,环境变量,命令,内

    linux没有该命令错误?

    linux没有该命令错误?,系统,第一,环境,命令,分析,软件,异常,文件,目录,空格,

    linux调出变量的命令?

    linux调出变量的命令?,系统,工作,工具,信息,地址,代码,标准,名称,官网,命令,l

    查看linux类型命令?

    查看linux类型命令?,系统,信息,命令,状态,数据,数字,情况,地址,类型,文件,lin

    linux命令错误代码?

    linux命令错误代码?,系统,密码,电脑,网络,手机,网址,软件,代码,设备,老板,Lin

    linux删除类型命令?

    linux删除类型命令?,系统,档案,命令,文件,名称,环境,数据,不了,目录,文件夹,

    linux命令主机名变量?

    linux命令主机名变量?,系统,主机名,查询系统,命令,终端,编辑,提示符,根目

    查看linux库类型命令?

    查看linux库类型命令?,系统,工作,信息,状态,电脑,命令,工具,代码,地址,发行,

    linux网卡类型命令?

    linux网卡类型命令?,网络,系统,地址,信息,设备,状态,服务,名称,名字,网卡,如

    linux命令忽略错误?

    linux命令忽略错误?,系统,地址,工作,信息,设备,命令,设计,灵活,观察,标准,lin

    linux变量是一个命令?

    linux变量是一个命令?,系统,信息,变量,名称,官网,地址,环境,代码,地方,命令,$

    linux中变量取余命令?

    linux中变量取余命令?,地址,工作,系统,数据,信息,命令,分析,目录,控制台,文

    linux查看命令类型用?

    linux查看命令类型用?,信息,系统,情况,命令,实时,工作,设备,电脑,文件,类型,

    linux命令三种类型?

    linux命令三种类型?,工作,地址,系统,标准,时间,管理,命令,目录,信息,文件,lin

    加载变量的linux命令?

    加载变量的linux命令?,工具,系统,名称,环境变量,环境,命令,用户,文件,变量,

    linux命令算术运算?

    linux命令算术运算?,系统,工作,基础,信息,管理,代码,命令,技术,服务,网络,别

    linux变量赋值命令?

    linux变量赋值命令?,标准,数据,数字,时间,系统,名称,变量,赋值,代码,环境,lin