此代码将无法编译:
class App {
Short foo() {
return 3;
}
void bar(Short s){
}
public static void main(String[] args) {
new App().foo();
new App().bar(3);
}
}
显示以下消息:
App.java:12: error: incompatible types: int cannot be converted to Short
new App().bar(3);
为什么编译器在返回3
的{{1}}中返回foo
时没有问题,但是对于参数Short
却不接受3
清单?
答案 0 :(得分:3)
我发现自己在这个问题上走了自己的尾巴,直到阅读JLS并基本上得出结论是,因为Java的创建者是这样做的。
关于new App().bar(3)
失败的原因,JLS对于使用装箱方法调用有一条规则:
5.3. Method Invocation Conversion
拳击转换(第5.1.7节)(可选),然后加宽参考转换
在这种情况下,参考转换意味着:
假设S是T的子类型(第4.10节),则存在从任何引用类型S到任何引用类型T的扩展引用转换。
因此,编译器会尽力尝试:
new App().bar(new Integer(3))
但是,由于Short
和Integer
并不是彼此的子类(实际上它们都是Number
的两个子类),因此无法进行扩展的引用转换。因此,此方法调用因您看到的编译器错误而失败。
关于允许以下内容的原因:
Short foo() {
return 3;
}
我们还可以看一下JLS关于分配转换的讨论。埋在里面,我们发现了以下内容:
5.2. Assignment Conversion 如果变量的类型为:
,则可以使用紧缩原始转换后跟装箱转换。
因此,编译器可以按以下方式处理foo()
方法:
Short foo() {
return Short.valueOf(3);
}