5

我无法理解这个问题,以及对 SCJP 1.6 自测问题答案的解释。这是问题所在:

class A { }
class B extends A { }
public class ComingThru {
    static String s = "-";
    public static void main(String[] args) {
        A[] aa = new A[2];
        B[] ba = new B[2];
        sifter(aa);
        sifter(ba);
        sifter(7);
        System.out.println(s);
    }
    static void sifter(A[]... a2) { s += "1"; }
    static void sifter(B[]... b1) { s += "2"; }
    static void sifter(B[] b1) { s += "3"; }
    static void sifter(Object o) { s += "4"; }
}

结果是什么?答案是-434,但让我失望的是这本书的解释。它与本章前面解释的概念有很大不同。

“通常,最后选择重载的 var-args 方法。请记住,数组是对象。最后,可以将 int 装箱为 Integer,然后将其“扩展”为 Object。”

拆分一下,有人可以进一步定义该解释吗?

  1. 通常,最后选择重载的 var-args 方法。
  2. 数组是对象(我实际上明白了,但为什么这与这个问题有关)。
  3. 可以将 int 装箱为 Integer,然后将其“扩展”为 Object。

谢谢!

4

2 回答 2

6

这本书试图解释为什么前两个重载从未被选中:因为 var-args 标记...使它们仅在其他所有可能的重载都失败时才使用。在这种情况下,这不会发生——以“记住”开头的两句话解释了为什么它没有发生,为什么在第一种和最后一种情况下存在其他可能的重载(第二种情况及其与第三种重载的匹配) sifter 是很明显的):一个数组是一个对象,一个 int 可以被装箱然后加宽为一个 Object,所以第 4 个重载匹配第一个和最后一个对 sifter 的调用。

于 2009-07-15T03:45:45.293 回答
4
  1. 当试图确定调用哪个方法时,编译器首先查找非可变参数方法(例如sifter(Object)),然后再考虑可变参数方法(例如sifter(A[]...)),此时两种方法都属于同一个类(或多或少)。

  2. 由于数组是一个Object,调用sifter(aa)将匹配sifter(Object),因此甚至不考虑sifter(A[]...)

  3. 从Java 5 开始,编译器可以“装箱”原语,即将原语值(例如int)转换为它们对应的Object(例如Integer)。因此对于sifter(6),编译器将 转换int 6Integer 6,因此它会匹配sifter(Object)方法。

于 2009-07-15T03:51:54.283 回答