Why type promotion takes precedence over varargs for overloaded methods

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 output of the above code is "int". But it must be "long" because the function of the byte type argument is already present. But here the program promotes byte values ​​to int, but it should not be.

Please can anyone clarify what is going on here?

+6
java method-overloading variadic-functions
source share
2 answers

Variable argument methods will always be the last to be selected by the compiler in case of overloaded methods. Advancing byte to int (extension-conversion) will be preferable to a method that accepts the var-arg parameter.

The reason for this is that the language must be backward compatible. Old features will take precedence over new features. An easy way to understand what JLS says about variable arguments is that the extension will beat the box, and the box will beat var-args.

+2
source share

JLS 15.12.2 is the corresponding specification bit to see here. In particular - my emphasis:

The rest of the process is divided into three phases to ensure compatibility with Java programming language versions prior to Java SE 5.0. Phase:

  • The first phase (Β§15.12.2.2) performs overload resolution without allowing box conversion or decompression or using the method call of the arity variable. If no applicable method is found at this stage, processing continues until the second phase.

    This ensures that any calls that were valid in the Java programming language prior to Java SE 5.0 are not considered ambiguous as a result of the implementation of arity variable methods, implicit boxing and / or decompression. Declaring a method of the arity variable method (Β§8.4.1) may change the method chosen to express the method call of this method, since the method of the arity variable is considered as a fixed arity method in the first phase. For example, declaring m(Object...) in a class that already declares m(Object) causes m(Object) no longer be selected for some invocation expressions (for example, m(null) ), since m(Object[]) more specific.

  • The second phase (Β§15.12.2.3) performs overload resolution when allowing boxing and unpacking, but still eliminates the use of the method invocation of the arity variable. If no applicable method is found at this stage, processing continues until the third phase.

    This ensures that the method is never selected by calling the method of the arity variable, if applicable by calling the fixed arity method.

  • The third stage (Β§15.12.2.4) allows you to combine overloading with the methods of the variable arity, boxing and unpacking.

In your case, the first phase finds a match without using the method call of the arity variable or box, hence the result. As noted in the spec, this is mainly for backward compatibility.

+10
source share

All Articles