请参阅以下代码:
// 1st method
private static void method(Object o){
System.out.println("object method");
}
// 2nd method
private static void method(Object... o){
System.out.println("object vararg method");
}
public static void main(String [] ar){
method(null); // 1st call
Integer value=null;
method(value); // 2nd call
}
我预计1st call
和2nd call
都应该调用1st method
,认为null
更愿意匹配Object
而不是Object...
vararg。但我错了。
1st call
已调用2nd method
2nd call
已调用1st method
我的问题是null
为什么或如何与Object...
vararg匹配而不是Object
代码?
答案 0 :(得分:2)
由于Object...
基本上是Object[]
,并且null
是有效的Object[]
,因此它将与最具体的匹配。
如果你有3个方法,第一个有Object
参数,第二个有SubClass
参数,最后一个有SubSubClass
参数,最后一个将被选中。
然而,如果您在原始代码中添加带有String
参数的方法,则会出现编译时错误,因为null
不再存在一个最具体的匹配项。
答案 1 :(得分:2)
JLS 15.12.2解释了这个确切的情况:
第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。
这保证了在Java SE 5.0之前在Java编程语言中有效的任何调用都不会因为引入变量arity方法,隐式装箱和/或取消装箱而被认为是不明确的。但是,变量arity方法(第8.4.1节)的声明可以更改为给定方法方法调用表达式选择的方法,因为变量arity方法在第一阶段被视为固定arity方法。例如,在已声明m(Object)的类中声明m(Object ...)会导致不再为某些调用表达式(例如m(null))选择m(Object),因为m(Object [] )更具体。