SC Java Programmer 6考试

时间:2012-01-08 18:51:30

标签: java

有来自考试的课程。任何人都可以解释“-434”的答案如何:

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.print(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";}
}

谢谢!

3 个答案:

答案 0 :(得分:7)

您可能知道,在调用出现了多个不同参数集的方法时,Java会尝试调用最具体的方法。因此,例如,sifter(Object)方法可以应用于任何对象,但如果已知对象为B[],则会调用更具体的sifter(B[])方法。

棘手的是,为了确保向后兼容性,当Java试图找出要调用的方法时,它首先会查看是否存在任何适用的非varargs方法。只有没有这样的方法才会考虑varargs选项。

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2

因此,在使用sifter()调用A[]时,非varargs方法sifter(Object)适用,因此编译器甚至不会考虑sifter(A[]...)

答案 1 :(得分:1)

编译器使用以下规则解析方法调用:(不提及声明/可见范围)
1,如果存在确切的签名匹配,则呼叫将解析为该方法 2a,如果参数是基元,则在没有匹配的情况下尝试将其打包。
2b,如果不存在匹配则尝试加宽,这意味着它将查找具有实际参数类型的超类型的声明。
3,如果不存在加宽的签名匹配,它将尝试匹配varargs。
如果仍然没有匹配,则表示编译时错误。(步骤2a和2b是互斥的)
基于这些规则:
-因为初始化 调用sifter(aa);解析为Object争论方法,因为编译器首先尝试扩展。 sifter(ba);解析为B[] arg-ed方法,因为它是精确的签名匹配,然后最后再次解析为Object方法,规则再次是编译器首先尝试扩展,然后尝试varargs。因此,方法调用的最终结果为434

答案 2 :(得分:-1)

您可能认为答案是-134。但它实际上是-434。

最后“4”来自参数“7”,它只对应于 Object 参数的那个。

“3”对应于直接静态 void sifter(B [] b1)

第一个“4”的原因是最近的参数是Object,因为“(A []​​ ... a2)”无效。 如果它是“(A ... a2)”,那么-134就是正确的。