• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

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

 
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Jesper de Jong
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 29
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 621
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks all from this post i realy got to learn somthing...!!!
 
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank.

Btw, how long do they need to fix a bug?
This bug was submitted on 23-Nov-2004.
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 29
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
[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 ]
 
Grow a forest with seedballs and this tiny ad:
a bit of art, as a gift, that will fit in a stocking
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic