Can you explain me why the result is "int"? I would expect it to be "long" provided the variable is a byte.
public class Test{
public static void printValue(int i, int j, int k){
System.out.println("int");
}
public static void printValue(byte...b){
System.out.println("long");
}
public static void main(String... args){
byte b = 9;
printValue(b,b,b);
}
}
The Java compiler must choose between the two matching methods. It will always choose a method that doesn't use variable arity (varargs) over one that does use it. It would rather promote all 3 arguments to int
to match the first printValue
than use varargs.
Section 15.12.2 of the JLS states:
The remainder of the process is split into three phases, to ensure compatibility with versions of the Java programming language prior to Java SE 5.0. The phases are:
- The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.
This guarantees that any calls that were valid in the Java programming language before Java SE 5.0 are not considered ambiguous as the result of the introduction of variable arity methods, implicit boxing and/or unboxing. However, the declaration of a variable arity method (§8.4.1) can change the method chosen for a given method method invocation expression, because a variable arity method is treated as a fixed arity method in the first phase. For example, declaring m(Object...) in a class which already declares m(Object) causes m(Object) to no longer be chosen for some invocation expressions (such as m(null)), as m(Object[]) is more specific.
- The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.
This ensures that a method is never chosen through variable arity method invocation if it is applicable through fixed arity method invocation.
- The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.
(bold emphasis mine)
A matching method (the first overload) is found in the first phase, so the compiler doesn't even consider the third phase -- allowing variable arity methods -- so int
is printed.
One way to choose the second overload (which counterintuitively prints long
) is to create an array explicitly so that the first overload can't match.
printValue(new byte[]{b,b,b});
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