I am preparing for a SCJP exam and when studying widening part it\'s given that widening beats both Boxing and Var-args in overloading but there is no clear explanation. Tri
Yes, the compiler "chooses the older style over the newer style", because of compatibility requirements. Imagine some code, written before Java 5 came out, that suddenly had a change of behaviour when compiled under Java 5! That would be bad.
Widening conversions have been around since the dawn of Java, but autoboxing and varargs are new to Java 5.
class Widen {
private static widen(long k) {
System.out.println("Converted to long: " + k);
}
private static widen(int ... k) {
System.out.println("Converted to varargs: " + k);
}
private static widen(Integer k) {
System.out.println("Converted to Integer: " + k);
}
public static void main(String ... args) {
int value = 3;
widen(value); // Output: Converted to long: 3
}
}
to solve above mind this:
widening beats boxing, boxing beats varargs
the out put will be Converted to long:3
The compiler has to keep compatibility with previous versions of Java. On top of that the compiler chooses the most performant / smallest change to the argument. Promoting to another primitive beats creating wrapper object and that beats creating an array with regards to memory usage and performance.
The reason that widening performs better is because it is a simple operation to sign extend, a single instruction for most CPUs. Boxing requires a heap allocation, and boxed objects are more expensive to access, requiring at least an additional memory access.
Even without the compatibility issue, it seems to me that you'd want the language to prefer the fastest overload first, as long as this behavior doesn't create any worse issues.
Here is an example of it:
class Widen {
private static void widen(long k) {
System.out.println("Converted to long: " + k);
}
private static void widen(int ... k) {
System.out.println("Converted to varargs: " + k);
}
private static void widen(Integer k) {
System.out.println("Converted to Integer: " + k);
}
public static void main(String ... args) {
int value = 3;
widen(value); // Output: Converted to long: 3
}
}
So all this means is that it will widen before autoboxing and using varargs. If we took out the method of widen with the long parameter, it would have chosen the autoboxing before the varargs.
widening beats boxing, boxing beats generics, generics beat varargs