7

在下面的代码中

class A {
    public void v(int... vals) {
        System.out.println("Super");
    }
}

class B extends A {
    @Override
    public void v(int[] vals) {
        System.out.println("Sub");
    }
}

然后我可以打电话给new B().v(1, 2, 3);//print Sub rather than Super这很荒谬但效果很好。如果我B改为

class B {
    public void v(int[] vals) {
        System.out.println("Not extending A");
    }
}

调用new B().v(1, 2, 3);将无效。您必须将其称为new B().v(new int[]{1, 2, 3});,为什么?

4

2 回答 2

7

在 JDK 1.7 下,您的示例无法编译,我认为它们不应该编译。

很容易看出为什么第二个版本没有 - 当B不扩展时A,根本没有 varargs 的指示,所以编译器没有理由将三个int参数的参数列表转换为单个int[]. 更有趣的情况是 where B does extend A

编译器找到一个v(int[] vals)使用可变参数的签名。规范中没有说它应该查找继承链以查找其他声明之一(可能有多个)是否使用可变参数。它出现在您的 JDK 1.6 版本中的事实表明这是一个编译器错误,此后已得到修复。(我刚刚也重现了 JDK 1.6.0_39 中的错误。)

基本上,如果您希望能够以B.v()可变参数样式的语法调用,B.v()则应使用可变参数声明。当然,如果您将其更改为编译时类型为A,那将起作用:

A a = new B();
a.v(1, 2, 3);

甚至(ick):

((A) new B()).v(1, 2, 3);

请注意,如果您与您一起编译,无论如何-Xlint都会收到警告:B

Test.java:14: warning: v(int[]) in B overrides v(int...) in A; overriding method
 is missing '...'
    public void v(int[] vals) {
                ^
于 2013-07-31T20:50:50.677 回答
0

由于 vararg 的工作方式,它不起作用。

如果你的方法是:

foo(int... par)

foo(new int[]{1, 2, 3});
foo(1, 2, 3);

这些都是有效的方法调用。但是,反过来也行不通。

如果你的方法是:

bar(int[] par)

bar(new int[]{1, 2, 3}); // Valid
bar(1, 2, 3); // Invalid!

第二次调用无效。如果方法有可变参数,它可以接受一个数组;如果它有一个数组参数,它只能接受一个数组,而不是一个参数序列!

于 2013-07-31T21:24:28.610 回答