有来自考试的课程。任何人都可以解释“-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";}
}
谢谢!
答案 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就是正确的。