继承中的方法签名

cha*_*_ma 7 java polymorphism inheritance

在下面的代码中

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以称之为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");
    }
}
Run Code Online (Sandbox Code Playgroud)

呼叫new B().v(1, 2, 3);将无效.你必须称之为new B().v(new int[]{1, 2, 3});,为什么?

Jon*_*eet 7

在JDK 1.7,无论你的例子编译,我不相信他们应该.

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

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

基本上,如果您希望能够以B.v()varargs样式语法调用,B.v()则应使用varargs声明.当然,如果你改变它以便编译时类型A,那将是有效的:

A a = new B();
a.v(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

甚至(ick):

((A) new B()).v(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

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

Test.java:14: warning: v(int[]) in B overrides v(int...) in A; overriding method
 is missing '...'
    public void v(int[] vals) {
                ^
Run Code Online (Sandbox Code Playgroud)