继承中的方法签名

时间:2013-07-31 20:48:17

标签: java inheritance polymorphism

在下面的代码中

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});,为什么?

2 个答案:

答案 0 :(得分:7)

在JDK 1.7下,你的例子都没有编译,我认为不应该这样做。

很容易理解为什么第二个版本没有 - 当B没有扩展A时,根本没有指示varargs,所以编译器没有理由转换为将int个参数的参数列表合并为一个int[]。更有趣的情况是B 扩展A

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

基本上,如果您希望能够以varargs样式语法调用B.v(),则应使用varargs声明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) {
                ^

答案 1 :(得分: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!

第二次通话无效。如果该方法具有vararg参数,则它可以接受数组;如果它有一个数组参数,它只能接受一个数组,而不是一系列参数!