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

1

7

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!

Porscheporsena answered 23/2, 2010 at 21:18 Comment(0)
N
9

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."

Neille answered 23/2, 2010 at 21:48 Comment(1)
I kinda thought that it tried the three approaches and the first one to be "invocable" would be invoked. Although the method takes (Integer... i), I sort of expected that boxing into an Integer would make that method "invocable". But, as you say, it seems that the subsequent "var-arg-ization" is also taken into account. Cheers!Porscheporsena

© 2022 - 2024 — McMap. All rights reserved.