重载方法选择

Overloading Method Selection

让我们考虑这个例子

public class C {

  public void method(String s, Integer i, Object... o) {
    System.out.println("method(String s, Integer i, Object... o)");
  }

  public void method(Object o, Integer i) {
    System.out.println("method(Object o, Integer i)");
  }
}

当我执行

C c = new C();
c.method("1", 1);

我期待 method 的第一个实现被调用,但我打印了这条消息

method(Object o, Integer i)

我是从 specs that methods with variable arguments (varargs) are not considered in the phase 1 上读到的,但这种行为对我来说并不直观。

因为你只发送了两个参数,所以会执行两个参数的方法,发送三个参数会执行三个参数的方法。

首先,您必须了解 OOP 的面向对象概念之一(及其 Java 语法)、多态性和重载。无论如何通过调用

c.method("1", 1);

你实际上是在调用第二个方法本身,它接受 2 个参数,而不是第一个似乎有 3 个或更多参数的方法。该程序实际上正在做它应该做的事情。

如果您需要调用第一个方法,请改用三个参数,因为可变参数通常接受一个或任意数量的参数。所以调用语句应该是这样的:

c.method("1", 1,"any argument");

如果你只想用两个参数调用第一个方法,那么使用这样的实现:

public class C {

    public void method(String s, Object... o) {
        System.out.println("method(String s, Integer i, Object... o)");
    }

    public void method(Object o, Integer i) {
        System.out.println("method(Object o, Integer i)");
    }

}

你传递了两个参数,所以编译器会考虑第二个方法,因为参数的数量与第二个方法匹配,所以编译器有两个参数,然后编译器检查参数的数据类型。 但是第二种方法的第一个预期参数是 "Object" 而你传递的是 "String"。

确定方法签名基于三个阶段:前两个阶段基于匹配非可变参数方法,而在第三阶段,考虑具有可变参数的方法。

Method with non var-args will have more priority over method with var-args if both methods seem to be called

 // least priority method if both method arguments matching with the calling one
 public void method(String s, Integer i, Object... o) {
    System.out.println("method(String s, Integer i, Object... o)");
  }

  public void method(Object o, Integer i) {
    System.out.println("method(Object o, Integer i)");
  }

规格如下:

Compile-Time Step 2: Determine Method Signature

  1. The first phase 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.
  2. The second phase performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.
  3. The third phase allows overloading to be combined with variable arity methods, boxing, and unboxing.

根据第 3 阶段规则:重载允许与 var-args 结合使用,即带有 var-args 的方法的优先级较低