wood burning stoves 2.0*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes (var-arg, Boxing, Widening) ambiguous call error Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "(var-arg, Boxing, Widening) ambiguous call error" Watch "(var-arg, Boxing, Widening) ambiguous call error" New topic
Author

(var-arg, Boxing, Widening) ambiguous call error

Ansar Shah
Greenhorn

Joined: May 02, 2007
Posts: 29
Hello


The above code gives compiler error of ambiguous call to go() method. When the var-arg are removed from the parameters of both versions of go() method, then it compiles fine. Ambiguous call comes only with var-arg. Can anyone explain this for me?

Thanks
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14074
    
  16

This is a difficult question, it requires some digging in the Java Language Specification to find out why it works like this.

First of all I replaced "Integer..." by "int..." in your first go() method; it still works the same (error with the varargs dots, no error without).

When there are multiple methods that match the call, Java normally chooses the most specific method. Section 15.12.2.5 of the JLS explains how this works for methods with a fixed number of arguments and for methods with a variable number of arguments ("variable arity" methods).

This paragraph in the JLS is hard to read and understand because of the formal language and symbols used. The symbol "<:" is explained in section 4.10. If I understand it correctly, the notation "T <: S" basically means that T is a subtype of S, or T is the same type as S. Section 4.10.1 says that long should be regarded as a direct supertype of int, so that means int <: long is true.

Now back to 15.12.2.5. It explains the rules that say when one method is more specific than another method, based on the argument types. When I read this carefully my conclusion is that both without and with the varargs dots, the "int..." version of the go() method is the most specific method. That means that in both cases the compiler should call the "int..." method.

So, either I am reading the JLS wrong or this is a bug in the Java compiler.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Ansar, it looks like you have stumbled onto an issue that is more complicated than you are likely to encounter on the real exam. So while it may certainly be worthwhile to understand what's going on, it's the sort of thing that people can drive themselves crazy by worrying about it unnecessarily. The level of detail in this discussion is deeper than you need for the exam. If you follow the discussion and learn from it, excellent. But if not, it's best not to worry too much about it. This goes for everyone who may be reading this.

On to the discussion...

This is very strange. I believe I can explain why the code in Anshar's original post is ambiguous, but so far I don't see why Jesper's modified version is ambiguous.

The problem with Anshar's code is that the wrapper class Integer is not a subtype of the primitive type long, and long is not a subtype of Integer. Thus, neither method can be said to be more specific than the other, and thus both methods are maximally specific, which means the method call is ambiguous.

However, when Jesper changed Integer to int, int is a subtype of long, and so it does seem that go(int... i) is more specific than go(long... i), and not vice versa. I don't know why the compiler complains that this is ambiguous. Perhaps we're both still missing something here.

Going back to the original question though:

[Ansar]: Ambiguous call comes only with var-arg. Can anyone explain this for me?

This is because of the three phases of identifying potentially applicable methods, described generally in JLS 15.12.2 and more specifically in JLS 15.12.2.2, JLS 15.12.2.3, and JLS 15.12.2.4.

Basically, first the compiler looks for methods without considering varargs or boxing. If no methods are found, then it looks again, considering boxing but not varargs. And if still no methods are found, it looks once more, considering both boxing and varargs.

In your original code (with varargs), the compiler can't find any methods at all on the first two attempts, and then on the third attempt it considers varargs and finds two methods, neither of which is more specific than the others.

If you remove the varargs, then the important difference between the methods is that one requires boxing, and the other doesn't. Thus, on the compiler's first attempt to find applicable methods, without considering varargs or boxing, it finds exactly one method: go(long i). And since it finds that one method, the compiler doesn't need to make a second or third attempt using boxing or varargs - it's done. It's found one applicable method, and that's good enough. If it had found two, it would have to decide which is more specific, but since it found only one, that's not an issue.


"I'm not back." - Bill Harding, Twister
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14074
    
  16

This is indeed a bug in the Java compiler!

Here is what I found in Sun's bug database: Bug ID: 6199075 Unambiguous varargs method calls flagged as ambiguous
Ansar Shah
Greenhorn

Joined: May 02, 2007
Posts: 29
Hello

Thanks a lot for such a fruitful discussion
Although it ended up as a compiler bug, but still learned a lot from your replies.


Thanks
dhwani mathur
Ranch Hand

Joined: May 08, 2007
Posts: 621
Thanks all from this post i realy got to learn somthing...!!!
Fedry Kemilau
Ranch Hand

Joined: Aug 06, 2007
Posts: 44
Thank.

Btw, how long do they need to fix a bug?
This bug was submitted on 23-Nov-2004.


Solve this code:<br /> <br />10010101100001111011011000010100000111001011011111100011110101111100110100001
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Now that the bug database is back online, we can read the bug report and see that the two overloads in the report are foo(int... i) and foo(double... d). Thus, both the varargs are primitive types, and the compiler should be able to determine that int is a subtype of double, therefore the foo(int... i) overload should be more specific - but the compiler's not saying that.

Thus, the bug report is analogous to Jesper's modified version of the problem above, where he changed Integer... to int.... That version of the problem does indeed show a bug in the compiler.

The bug report is not similar enough to Ansar's original problem though. In that version Integer is not a subtype of long, and long is not a subtype of int - therefore neither overload is more specific than the other, and there is no most specific method. In Ansar's original code, the compiler is correct; the code is ambiguous according to the specification. It's not a bug.
Ansar Shah
Greenhorn

Joined: May 02, 2007
Posts: 29
Hello Jim

Thanks for your valuable comments.
What I had in my mind while creating the originally posted scenario was the concept of Boxing. The question was that, Is the compiler intelligent enough to box Integer to int before checking for the most specific version of the overloaded method? and the answer was YES.
Then I introduced var-args in the parameters. This is where the problem came.


The above code gives compiler error of ambiguous call to go() method. When the var-arg are removed from the parameters of both versions of go() method, then it compiles fine. Ambiguous call comes only with var-arg. Can anyone ...


Thanks
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
[Ansar]: When the var-arg are removed from the parameters of both versions of go() method, then it compiles fine. Ambiguous call comes only with var-arg.

Yes, I talked about this in my first post in this thread, above.
[ August 15, 2007: Message edited by: Jim Yingst ]
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: (var-arg, Boxing, Widening) ambiguous call error
 
Similar Threads
Overloading with Var-args and Boxing Doubt
var-args overloading compiler error: ambiguous
Overloaded varargs param doubt
overloaded var - args
Var-Args Doubt