I am surprised by seeing the output of this code :
public class File
{
public static void main(String[] args)
{
movie();
}
static void movie(double... x)
{
System.out.println("No varargs");
}
static void movie(int... x)
{
System.out.println("One argument");
}
}
It outputs,
One argument
Why is it so ?
I thought that this code would not compile because the call to movie()
is ambiguous, but it runs fine and outputs One argument
.
If I modify the code to:
public class File
{
public static void main(String[] args)
{
movie();
}
static void movie(boolean... x) //Changed the parameter type to boolean from double
{
System.out.println("No varargs");
}
static void movie(int... x)
{
System.out.println("One argument");
}
}
There is an error message.
Why does the first code run fine, but the second gives an error?
There can be only one variable argument in a method. Variable argument (Varargs) must be the last argument.
Each method can only have one varargs parameter. The varargs argument must be the last parameter.
Generally speaking, you should not overload a varargs method, or it will be difficult for programmers to figure out which overloading gets called.
Rules for varargs:There can be only one variable argument in the method. Variable argument (varargs) must be the last argument.
This behaviour is due to the fact that int
is more specific than double
while there is no such comparison between int
and boolean
.
As specified in the JLS section 15.12.2.5 (emphasis mine):
One applicable method m1 is more specific than another applicable method m2, for an invocation with argument expressions e1, ..., ek, if any of the following are true:
- ...
- m2 is not generic, and m1 and m2 are applicable by variable arity invocation, and where the first k variable arity parameter types of m1 are S1, ..., Sk and the first k variable arity parameter types of m2 are T1, ..., Tk, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ k). Additionally, if m2 has k+1 parameters, then the k+1'th variable arity parameter type of m1 is a subtype of the k+1'th variable arity parameter type of m2.
What more specific actually means is later defined with subtyping:
A type S is more specific than a type T for any expression if S <: T.
This means that S
is more specific than T
is S
is a subtype of T
. For primitive types, this comes down to the following properties:
- double > float
- float > long
- long > int
- int > char
- int > short
- short > byte
Notice that boolean
is not there.
As such,
public static void main(String[] args) {
movie();
}
static void movie(int... x) { }
static void movie(short... x) { }
static void movie(double... x) { }
static void movie(byte... x) { }
compiles and movie(byte... x)
will be called because it is the most specific.
However,
public static void main(String[] args) {
movie();
}
static void movie(int... x) { }
static void movie(boolean... x) { }
does not compile because boolean
cannot be compared to int
.
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