Interview with Java Primitive Widening

Can you explain to me why the result is "int"? I expect it to be “long” if 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); } } 
+5
source share
2 answers

The Java compiler must choose between two matching methods. He will always choose a method that does not use the arity (varargs) variable over the one that uses it. This would rather contribute to all 3 int arguments to match the first printValue than using varargs.

Section 15.12.2 of the JLS states:

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 unboxing, 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. However, declaring a method to an arity variable (§8.4.1) may change the method chosen to express the method call of this method, since the arity variable method 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) to no longer be selected for some invocation expressions (such as m (null)), like m (Object [])) is more specific.

  1. 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 at this stage no applicable method is found, 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.

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

(my bold accent)

The matching method (first overload) is found in the first phase, so the compiler does not even consider the third phase - the methods of the arity variable allow - therefore, an int is printed.

One way to select the second overload (which counterintuitively prints long ) is to create an array explicitly so that the first overload cannot match.

 printValue(new byte[]{b,b,b}); 
+12
source

Hi, the result is "int" because when you started the main function, you did not print the Value with one argument, but rather with 3 arguments. therefore, the compiler suggested that you reference the first printValue, which has 3 parameters. Since you did not use this parameter inside the function, all that is good is without any runtime error. I would say on the other hand that it is not a good practice to find the type of a variable in this way. A better way would be to use an if if statement. And you can refer to this post for information on how to find a type in java: How do you know the type of a variable in java?

-1
source

Source: https://habr.com/ru/post/1240472/


All Articles