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?
The method signature in java is defined as the structure of the method that is designed by the programmer. The method signature is the combination of the method name and the parameter list. The method signature depicts the behavior of the method i.e types of values of the method, return type of the method, etc.
The signature of a method consists of the name of the method and the description (i.e., type, number, and position) of its parameters. Example: toUpperCase() println(String s)
Having two or more methods with the same name and signature as method in the parent class is known as method overriding. Method overriding allows us to invoke functions from base class to derived class.
In Java, a method signature is part of the method declaration. It's the combination of the method name and the parameter list. The reason for the emphasis on just the method name and parameter list is because of overloading. It's the ability to write methods that have the same name but accept different parameters.
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) {
^
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With