3

谁能解释为什么第一种方法比第二种方法更好?

我知道这个重载规则(除了首先编译器找到合适的参数)

  1. 扩大
  2. 自动装箱
  3. 可变参数

代码:

public class Proba{

    public static void show(Object ... args){
        System.out.println("Object ...");
    }

    public static void show(Integer[] ... args){
        System.out.println("Integer ...");
    }

    public static void main(String[] args) {
        Integer[] array = {3,2,5,1};
        show(array);        
    }
}

控制台Object ...

4

2 回答 2

4

Java 中的方法解析规则要求在尝试这些功能进行匹配之前,在没有自动(取消)装箱和可变数量的情况下尝试匹配。这确保了与早于这些功能的语言版本的源代码兼容性。

JLS(§15.12.2)中描述了重载解决的规则:

确定适用性的过程从确定可能适用的方法开始(§15.12.2.1)。

该过程的其余部分分为三个阶段,以确保与 Java SE 5.0 之前的 Java 编程语言版本兼容。阶段是:

  1. 第一阶段(第 15.12.2.2 节)执行重载决议,不允许装箱或拆箱转换,或使用变量 arity 方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。这保证了在 Java SE 5.0 之前在 Java 编程语言中有效的任何调用都不会因为引入可变参数方法、隐式装箱和/或拆箱而被认为是模棱两可的。但是,变量 arity 方法的声明(第 8.4.1 节)可以更改为给定方法方法调用表达式选择的方法,因为变量 arity 方法在第一阶段被视为固定 arity 方法。例如,声明 m(Object...

  2. 第二阶段(第 15.12.2.3 节)执行重载决议,同时允许装箱和拆箱,但仍排除使用变量 arity 方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段。这确保了一个方法永远不会通过可变的方法调用来选择,如果它可以通过固定的方法调用来应用的话。

  3. 第三阶段(第 15.12.2.4 节)允许将重载与可变参数方法、装箱和拆箱相结合。

在泛型方法(第 8.4.4 节)的情况下,决定一个方法是否适用需要确定类型参数。类型参数可以显式或隐式传递。如果它们是隐式传递的,则必须从参数表达式的类型中推断出它们(第 15.12.2.7 节)。

如果在适用性测试的三个阶段之一中确定了几种适用方法,则选择最具体的一种,如第 15.12.2.5 节所述。

在您的示例中,步骤 1 中有两个候选方法:带有Object[]参数的方法和带有Integer[][]参数的方法。您调用站点的参数类型是Integer[]. 由于Object[]可从 分配Integer[],但Integer[][]不是,因此找到了一个适用的方法,并且重载解决方案在那里停止。在这种情况下,永远不会达到第 2 步和第 3 步。

于 2013-10-30T20:59:51.450 回答
1

迈克是正确的;有3个阶段,

15.12.2.2。第 1 阶段:识别子类型适用的匹配 Arity 方法

15.12.2.3。阶段 2:识别方法调用转换适用的匹配 Arity 方法

15.12.2.4。阶段 3:确定适用的可变 Arity 方法

show(Object[])在第一阶段被选中,但show(Integer[]...)只能在第三阶段被选中。

如果第一个方法签名更改为show(Object[] ... args),您将看到预期的结果。

如果将第二个方法签名更改为show(Integer ... args),您还将看到预期的结果。该方法也适用于阶段 1,并且比show(Object...)


如果我们有

public static void show(Object ... args){
    System.out.println("Object ...");
}

static class IntArray{}

public static void show(IntArray ... args){
    System.out.println("IntArray ...");
}

show(new IntArray());

它打印预期的IntArray ...。这里IntArray不是Object[].


这太令人困惑了。程序员通常不知道这些阶段;他们考虑所有适用的方法以及其中最具体的一种。如果规范也这样做可能会更好。

于 2013-10-30T21:21:03.273 回答