Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SCJP question: Java method overloading with var-args. What is the rationale?

Why does the following program throw an exception?

public class MainClass{
  public static void main(String[] argv){
       callMethod(2);
  }
  public static void callMethod(Integer... i){
       System.out.println("Wrapper");
  }
  public static void callMethod(int... i){
       System.out.println("Primitive");
  }

}

The method callMethod(Integer[]) is ambiguous for the type MainClass

OK, I can see that either of the two methods will work (if the other is commented out), but I also know that there is hierarchy on what happens if a primitive is not exactly matched by the type of the input of a method.

The first thing that is tried is to widen the primitive. So, if there was a third method:

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

The code would print long

The second thing is to box the primitive. So if there was a method taking an Integer, that would be the one invoked.

The third priority is the var-args.

Based on the above priority, I would expect that the second priotity be the case. I would expect the int to be wrapped into an Integer and the (Integer...) would be invoked. But of course this does not happen. Instead, the exception is thrown.

Does anyone see and can explain why the prioritization does not apply in this example?

Cheers!

like image 631
Markos Fragkakis Avatar asked Feb 23 '10 21:02

Markos Fragkakis


People also ask

What is the purpose of overloading a method in Java?

Method overloading is a programming technique that allows developers to use the same method name multiple times in the same class, but with different parameters.

What is the most practical reason to create an overloaded method?

Method overloading is useful because then you can route all of the operations through a single, generic method. This means that whenever an internal representation changes, you only have to change that generic method, and all your other specialized methods still work the same. Also, consider your provided example.


1 Answers

You are right that widening comes before boxing, which in turn comes before var-args.

But you seem to be treating the first method as callMethod(Integer i), not callMethod(Integer... i). Since both methods use var-args, there's a priority tie. That is, neither one meets the criteria for boxing alone, but both meet the criteria for var-args.

Remember that it's illegal to widen, then box (although I did some research before posting this answer and found that it IS legal to box, then widen). Similarly, you won't get box, then var-args behavior; the compiler skips right to the var-args step and sees two methods that take var-args.

EDIT: I should clarify that you WILL get box-then-var-args behavior if there's no ambiguity. In other words, if there was only one callMethod(), and it took Integer... i, you would get "Wrapper."

like image 171
Pops Avatar answered Oct 10 '22 03:10

Pops