Just when I thought I understood JLS15.12 as it applied to varargs, here's this example:
package com.example.test.reflect;
public class MethodResolutionTest2 {
public int compute(Object obj1, Object obj2) {
return 42;
}
public int compute(String s, Object... objects)
{
return 43;
}
public static void main(String[] args) {
MethodResolutionTest2 mrt2 = new MethodResolutionTest2();
System.out.println(mrt2.compute("hi", mrt2));
System.out.println(mrt2.compute("hi", new Object[]{mrt2}));
System.out.println(mrt2.compute("hi", new Object[]{mrt2, mrt2, mrt2}));
}
}
which prints out
42
43
43
I understand the first line: JLS15.12 says method resolution happens in phases, and phases 1 and 2 ignore varargs methods to find out if there's a compatible method, with phase 3 (include varargs) happening only if phases 1 and 2 fail. (See the JLS and this SO question.) So compute(String s, Object... objects)
always gets ignored if compute(Object obj1, Object obj2)
applies.
But I don't understand why 43 is printed for the other two lines. An Object[]
is also an instance of an Object
, so why does it match the varargs method?
edit:
...and this
Object arg2 = new Object[]{mrt2};
System.out.println(mrt2.compute("hi", arg2));
prints 42
.
In section 8.4.1:
If the last formal parameter is a variable arity parameter of type
T
, it is considered to define a formal parameter of typeT[]
.
Since you're explicitly providing an array, this allows the second two calls to match the variable arity method in the first phase, without consideration of variable arity.