方法重载 - 对象与对象可变参数

Method oveloading - Object vs Object vararg

查看下面的代码:

// 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 call2nd call 都应该调用 1st method,认为 nullObject... 更愿意匹配 Object 可变参数。但我错了。

我的问题是 null 为什么或如何匹配我的代码中的 Object... vararg 而不是 Object

因为 Object... 本质上是 Object[],并且由于 null 是有效的 Object[],它将匹配最具体的一个。

如果你有 3 个方法,第一个有 Object 参数,第二个有 SubClass 参数,最后一个有 SubSubClass 参数,最后一个将被选择。

而如果您将带有 String 参数的方法添加到您的原始代码中,则会出现编译时错误,因为不再有 null 的最具体匹配项。

JLS 15.12.2 解释了这个确切的场景:

The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

This guarantees that any calls that were valid in the Java programming language before Java SE 5.0 are not considered ambiguous as the result of the introduction of variable arity methods, implicit boxing and/or unboxing. However, the declaration of a variable arity method (§8.4.1) can change the method chosen for a given method method invocation expression, because a variable arity method is treated as a fixed arity method in the first phase. For example, declaring m(Object...) in a class which already declares m(Object) causes m(Object) to no longer be chosen for some invocation expressions (such as m(null)), as m(Object[]) is more specific.