为什么我可以这样做:
short a = 5;
但不是这样:
void setNum(short a);
setNum(5);
它抛出:
从int到short
的可能有损转换
我知道5是一个整数字面值,你必须强制转换它。我也明白,如果值不是常数,那么显然需要抛出该错误,因为该值可能达到短类型的限制。但是为什么如果编译器知道我传递了一个short可以容纳的常量(如在赋值中),它不会让它编译?我的意思是,它们之间有什么区别?
答案 0 :(得分:10)
为了理解分配类型转换在拒绝调用的同时工作的原因,必须参考narrowing primitive conversions的Java语言规范主题和该转换的上下文:assignment context和invocation context。
根据JLS,如果出现以下情况,赋值上下文中允许缩小原语转换:
如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。
...在分配给int
时,5
常量short a
符合您的情况。
调用上下文中不允许进行此类缩小基元转换,这解释了为什么在传递setNum(short)
常量int
时,对5
的调用失败。< / p>
但是为什么如果编译器知道我传递了一个short可以容纳的常量(如在赋值中),它不会让它编译?我的意思是,它们之间有什么区别?
JLS一定不想用这个额外的逻辑来加重编译器的负担。在调用的情况下,与形式参数类型匹配的参数是一个表达式 - 编译器已经必须确定类型,但是它也不需要检查表达式的值是否也可以安全地缩小。在这种情况下,作为一个常量,很明显我们它可以,但在执行上下文中,编译器不允许打扰该检查,并且实际上是正确的,以禁止它。
应该相当清楚的是,当允许使用表达式时,如果在不丢失精度的情况下无法进行缩小,就会更容易出现错误,因此JLS和编译器在所有情况下都不允许这样做。
在numeric context中也是如此,因此声明:
short a = 5;short b = a * 5;
...同样不允许,尽管明显包含正确缩小的常数。
答案 1 :(得分:0)
键入5
时,这会自动为整数。我不确定你使用的是什么IDE会给你错误,但它警告你的原因是因为你将更大的存储容量值转换为更小的存储容量值,虽然不是你的情况,但可能会导致你失败数据。这称为缩小转换。
整数可以保存32位数据,而短路只能保存16位数据。所以,例如(实际上数字会大得多),一个int的值等于50,然后你将它转换为short,数据将被切割为“5”,因为short没有足够大的内存分配。
您发布的代码无法正常工作,因为在您定义短片时如下:
short a = 5;
你是直接创造一个短线,而且这个数字足够小,以至于短线可以保持它。当你单独输入“5”作为方法参数时,它被作为一个整数处理,而JVM并不知道它是一个小而且安全的短路。要使“5”适合作为方法的参数,您需要使用缩小转换将其转换为short,如下所示:
setNum((short) 5);
但是如上所述,如果你实际上并不知道int的值,并且你不确定它是否足够小就可以变成一个short,这可能会在你的代码中产生错误,因为其中一些数字将是砍掉了。
(Here是关于此的一些Oracle文档)