Reputation: 786
In the code below
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");
}
}
Then I can call new B().v(1, 2, 3);//print Sub rather than Super
which is ridiculous but does work well. If I change B
to
class B {
public void v(int[] vals) {
System.out.println("Not extending A");
}
}
the call to new B().v(1, 2, 3);
will be invalid. You have to call it as new B().v(new int[]{1, 2, 3});
, why?
Upvotes: 7
Views: 433
Reputation: 1503040
Under JDK 1.7, neither of your examples compiles, and I don't believe they should.
It's easy to see why the second version doesn't - when B
doesn't extend A
, there's no indication of varargs at all, so there's no reason why the compiler should possibly convert an argument list of three int
arguments into a single int[]
. The more interesting situation is where B
does extend A
.
The compiler finds a signature of v(int[] vals)
which doesn't use varargs. There's nothing in the spec to say it should look up the inheritance chain to find whether one of the other declarations (there could be multiple ones) uses varargs. The fact that it appears to in your version of JDK 1.6 suggests that was a compiler bug which has since been fixed. (I've just reproduced the bug in JDK 1.6.0_39 as well.)
Basically, if you want to be able to invoke B.v()
in a varargs-style syntax, B.v()
should be declared using varargs. Of course, if you change it so that the compile-time type is A
, that would work:
A a = new B();
a.v(1, 2, 3);
Or even (ick):
((A) new B()).v(1, 2, 3);
Note that if you compile with -Xlint
you get a warning about B
anyway:
Test.java:14: warning: v(int[]) in B overrides v(int...) in A; overriding method
is missing '...'
public void v(int[] vals) {
^
Upvotes: 7
Reputation: 713
It doesn't work work because of the way vararg works.
If your method is:
foo(int... par)
foo(new int[]{1, 2, 3});
foo(1, 2, 3);
These are both valid method calls. However, it doesn't work the other way around.
If your method is:
bar(int[] par)
bar(new int[]{1, 2, 3}); // Valid
bar(1, 2, 3); // Invalid!
The second call will be invalid. If the method has a vararg parameter, it can accept an array; if it has an array parameter, it can only accept an array, not a sequence of parameters!
Upvotes: 0