Java Varargs边缘案例混乱

时间:2014-06-20 10:14:37

标签: java variadic-functions

我有点困惑:

void a(){
 Log.d(TAG, "Noargs");
}
void a(int... s){
 Log.d(TAG, "Varargs");
}

我的第一个问题是如果我打电话给()会记录什么;? 请尝试猜测,因为我试图说明与此混淆。我测试了它,答案就在问题的最后。

真正的问题是Varargs是如何工作的,JVM如何知道你调用哪种方法,因为调用它们的方式是一样的?

还有一些Java(或计划中的东西)允许这个

AS3 Code: function sayHello(somebody:String = “world”):void{}
//This allows you to specify default values of arguments and have them as optional

答案是Noargs甚至Ecipse引用了这种方法。

1 个答案:

答案 0 :(得分:1)

您正在观察的行为是因为Java 始终根据您传递给它的参数选择重载方法的最具体版本({{ 3}})。

根据您的情况:

void a() {
    Log.d(TAG, "Noargs");
}

void a(int... s) {
    Log.d(TAG, "Varargs");
}

a()的调用与void a() { ... }方法完全匹配 - 它是给定参数的方法的最具体的版本。当您删除void a() { ... }时,varargs方法将成为最具体的版本,因此将被调用。

您可以更进一步:

public class VarargsTest {

    public static void a(int... s) {
        System.out.println("int varargs invoked.");
    }

    public static void a(short... s) {
        System.out.println("short varargs invoked.");
    }

    public static void a(long... s) {
        System.out.println("long varargs invoked.");
    }

    public static void a(byte... s) {
        System.out.println("byte varargs invoked.");
    }

    public static void main(String... args) {
        a();
    }
}

这会调用byte...的{​​{1}}重载。如果删除该版本,则会调用a版本,然后调用short...,最后调用int...

如果您改为添加另一个带有long...的重载作为参数,它会成为编译错误,因为char...char具有相同的特性 - 编译器无法确定哪个版本是除非你明确地为方法调用提供一个参数,否则调用正确的。