Reputation: 133
I have a two overloaded methods: foo
and bar
//Object[]... vs Integer[]...
public static String foo(Object[]... args) { return "Object[] args"; }
public static String foo(Integer[]... args) { return "Integer[] args";}
//Object... vs Integer[]...
public static String bar(Object... args) {return "Object args";}
public static String bar(Integer[]... args) {return "Integer[] args";}
Now when I use them like:
Integer[] i = { 5 };
System.out.println(foo(i));//Object[]... vs Integer[]...
System.out.println(bar(i));//Object... vs Integer[]...
I am getting
Integer[] args
Object args
Here is the question: why do we have 2 different outputs?
Integer[]
can be implicitly cast to both Object
, and Object[]
.
Upvotes: 13
Views: 511
Reputation: 828
This is basically compiler deciding to call the most specific method among all.
When you call
System.out.println(foo(i));//Object[]... vs Integer[]...
it will call the foo(Integer[]... args)
Because at run time the JVM delegates the call to the method with Integer[][]
argument and not method with Object[][]
param as specified by varags. As it will be more specific to call method with Integer[][] rather than Object[][].
In the later statement, when you call
System.out.println(bar(i));//Object... vs Integer[]...
it will go to the bar(Object... args)
Again by using varags, the type of param will be Object[] and not Object[][]. Again the compiler will call the most specific method which will be the one having Object... args
.
If you change the method signature by removing varags as per following:
//Object... vs Integer[]...
public static String bar(Object args) {
return "Object args";
}
public static String bar(Integer[] args) {
return "Integer[] args";
}
then you will notice that it will call the bar(Integer[] args)
as it is more specific to the method call.
So to be more precise as per JLS Subtyping among Array Types,
This means that a call of Integer[] will be made to method having Integer[][] and not Object[][]. Where as a call of Integer[] will be made to Object[] rather than Integer[][].
See here for choosing the most specific method.
Upvotes: 4
Reputation: 59263
In the first case, the type of args is actually Integer[][], i.e., your array was boxed up into another array by varargs. The compiler chooses the Integer[] version because it is the most specific type.
In the second case, args == i and is an Integer[]. In this case, the compiler had to choose between wrapping it up in a new array to call the Integer[]... version or just casting your Integer[] to an Object[]. It chose the second one because that's the rule.
The moral of the story is: don't overload varargs methods -- it's confusing.
Upvotes: 3