Sunday, July 12, 2009

Method overloading with Widening, Boxing and Varargs

With the introduction of boxing and varargs in Java 1.5, there are new rules to remember wrt overloaded methods that include widening, boxing and varargs. Key rule to remember is widening always wins over boxing and varargs when present individually. So mathematically, widening > boxing > varargs in that order. There is a catch with widening reference variables. The reference variable widening should satisy the IS-A test. Here is a simple example:



public class BoxWidenVarArgs {

public static void pickMe(Integer i) {
System.out.println("Integer ");
}
public static void pickMe(int... i) {
System.out.println("varargs int ");
}
public static void pickMe(short i) {
System.out.println("short");
}
public static void pickMe(Byte i) {
System.out.println("Byte ");
}
public static void pickMe(byte... i) {
System.out.println("varargs byte");
}
public static void onlyInteger(Integer i) {
System.out.println("Integer");
}

public static void main(String[] args) {
byte b = 1;
pickMe(b); //picks widening over boxing and varargs
int i = 10;
pickMe(i); //As no widening is present, picks boxing over varargs
/**
* compilation error, cannot widen from Byte to Integer as Byte
* is not a Integer, IS-A test fails!
*/
//onlyInteger(new Byte(b));
}

}




Ouput:
short
Integer

Here are possible combinations of Widening, boxing and varargs:

Combining Widening and Boxing:
Can we widen and box, is this allowed? The rule to remember is that first widening then boxing ( i.e. Widen+Box) is not allowed. So a short can be widened to an int but a short cannot be widened and boxed to an Integer.


public class WidenAndBox {

public static void pickMe(Integer i) {
System.out.println("Integer");
}
public static void main(String[] args) {
short s = 2;
//Compilation error. Not allowed.
//pickMe(s);

}

}




Combining Boxing and Widening:
First boxing and then widening is allowed provided the widening satisfies the IS-A relationship. So a short can be boxed to a Short and then widened to a Number or Object but a short cannot be boxed to a Short and then widened to a Integer or String because it does not satisfy the IS-A relation.

Combining varargs with widening/boxing:
You can widen and then combine varargs. You can box and combine with varargs. However you cannot have overloaded methods that has widening+varargs and boxing+varargs. You can combine varargs with either widening or boxing.


public class LegalCombinations {

public static void pickMe(Number n) {
System.out.println("Number");
}
public static void wideningVarArgs(Integer... i) {
System.out.println("Integer...");
}
public static void boxingVarArgs(long... i) {
System.out.println("long...");
}

public static void main(String[] args) {
short s = 2;
pickMe(s); //Boxing and Widening
int i = 1;
wideningVarArgs(i); //combination of widening and varargs
boxingVarArgs(i); //combination of boxing and varargs
}

}



The following causes compilation error as discussed above:
public class IllegalCombinations {

public static void withVarArgs(Integer... i) {
System.out.println("Integer...");
}
public static void withVarArgs(long... i) {
System.out.println("long...");
}

public static void main(String[] args) {
int i = 1;
/**
* Compilation error. Cannot have 2 overloaded methods one using
* boxing+varargs and another using widening+varargs.
* Can have one or the other.
*/
//withVarArgs(i);
}

}

Also remember varargs are always chosen last. So if you have 2 overloaded methods one with boxing + widening and and one with varargs, compiler will choose boxing+widening over varargs.

Summary
:
  • used individually, widening > boxing > varargs
  • varargs are always chosen last, they always lose.
  • reference variables have to satisfy IS-A test while widening
  • widening then boxing is not permitted. 
  • boxing then widening is permitted.
  • varargs can be combined with wither boxing or widening.

No comments:

Post a Comment