为什么我可以将整数文字分配给短类型变量但不分配给短类型方法参数?

Gab*_*lBB 15 java primitive short

我为什么这样做:

short a = 5;
Run Code Online (Sandbox Code Playgroud)

但不是这个:

void setNum(short a);

setNum(5);
Run Code Online (Sandbox Code Playgroud)

它抛出:

从int到short的可能有损转换

我知道5是一个整数字面值,你必须强制转换它.我也明白,如果值不是常数,那么显然需要抛出该错误,因为该值可能达到短类型的限制.但是为什么如果编译器知道我传递一个short可以容纳的常量(如在赋值中)它不会让它编译?我的意思是,他们之间有什么区别?

jav*_*ett 10

为了理解为什么赋值类型转换在拒绝调用时工作,必须引用Java语言规范主题来缩小原始转换转换的上下文:赋值上下文调用上下文.

根据JLS,如果符合以下条件,则允许在赋值上下文中缩小基元转换:

如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示.

......,你的情况下,用火柴int不变5时,分配给short a.

调用上下文中不允许这种缩小的原始转换,这解释了为什么setNum(short)在传递int常量时调用失败5.

但是为什么如果编译器知道我传递一个short可以容纳的常量(如在赋值中)它不会让它编译?我的意思是,他们之间有什么区别?

JLS一定不想用这个额外的逻辑来加重编译器的负担.在调用的情况下,与形式参数类型匹配的参数是一个表达式 - 编译器已经必须确定类型,但是它也不需要检查表达式的值是否也可以安全地缩小.在这种情况下,是一个常数,它很清楚,我们认为它可以,但在执行上下文的编译器允许不与理会检查,并在-其实正确禁止它.

应该相当清楚的是,当允许表达式时,在不丢失精度的情况下,在不能缩小范围的情况下蠕虫会更容易蠕变,因此JLS和编译器在所有情况下都不允许它.

数值上下文中也是如此,因此声明:

short a = 5;short b = a * 5;
Run Code Online (Sandbox Code Playgroud)

...同样不允许,尽管明显包括正确缩小的常数.