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)
...同样不允许,尽管明显包括正确缩小的常数.