0
votes
public class Aman {
    void m(Byte b, Integer i) {     // autoboxing, autoboxing

    }
    void m(Number n, int i) {       // autoboxing -> widening, no conversion

    }
    public static void main(String[] args) {
        byte b = 23;
        Aman obj = new Aman();
        obj.m(b, 24);
    }
}

I have read this http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2 document but can

someone please explain step by step why the method invocation is giving ambiguous error, through the

steps described in this document.

2

2 Answers

1
votes

From the documentation you linked

The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

Nothing happens here because none of the methods match (byte, int) without boxing one of the arguments.

The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.

In this step, both methods match if you do some boxing on the arguments. If you box byte, the arguments match

void m(Number n, int i) {   

if you box the byte and the int, the argument match

void m(Byte b, Integer i) {  

So several methods are applicable.

If several applicable methods have been identified during one of the three phases of applicability testing, then the most specific one is chosen, as specified in section §15.12.2.5.

If you go through all those rules, you'll find there is no more specific method, so the call is ambiguous.

1
votes

First of all, there is no applicable method signature that doesn't use boxing/unboxing, so the compiler looks for all signatures that are applicable with boxing (spec ref). It finds that both methods are applicable.

Then, it checks if one is more specific than the other. This requires each parameter type of one method to be a subtype of the corresponding parameter type of the other method. Since int and Integer are not comparable, the call is ambiguous.

The reason that calls to m(Integer) and m(int) are normally not ambiguous is that the appropriate method is found in "phase one" in the linked spec, before boxing is even considered. Here, you could resolve the ambiguity by changing the call to:

obj.m(Byte.valueOf(b), 24);