• Post Reply Bookmark Topic Watch Topic
  • New Topic

Ambiguous reference with varargs  RSS feed

 
Lucien van Wouw
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

Why is the compiler unable to infer the intended overloaded method directly when using a literal primitive int and Integer type arguments?
It does compile indirectly when lower types like byte and short are specified as arguments. In that case the compiler works its way up to the primitive int and identify the method doA(int[] i, int... args) fine.

 
Henry Wong
author
Sheriff
Posts: 23030
120
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Lucien van Wouw wrote:
Why is the compiler unable to infer the intended overloaded method directly when using a literal primitive int and Integer type arguments?


Unfortunately, the rules as currently written, simply does not distinguish a "difference" between the two options (http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.3).

With the case of byte/short, an implicit cast to int and then followed by an autobox to Integer ... well ... that combination is not listed as allowed, hence, it isn't ambiguous. There is only one option.

Of course, you can argue that using autoboxing should be distinguished from not using autoboxing -- and you would be correct (https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2). Unfortunately, varargs has even lower "priority" than autoboxing, so, that rule does not apply.


IMHO, this section of the JLS is still a mess. And hopefully, it will be updated in the future.

Henry
 
Campbell Ritchie
Sheriff
Posts: 54078
130
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

I think you are supposed to call byte and short “narrower” types than int.
To sort out the compiler error, you will have to go through the difficult subject of method overloading in the Java® Language Specification. That is by no means easy to read. The mechanism for resolving overloading is even harder to understand.
I think simply that the compiler is faced with the challenge of working out whether to box your ints to an Integer or use them straight. In which case it cannot reliably distinguish between an Integer[] and an int[]. If you cast one of the arguments to a narrower type, the compiler has no ambiguity. It can use a widening conversion to an int or a boxing conversion (which would be to a Short) but not both. It can therefore not convert your short to an Integer, but it can convert the short to an int, so that removes the ambiguity.
 
Tony Docherty
Saloon Keeper
Posts: 3214
78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:If you cast one of the arguments to a narrower type, the compiler has no ambiguity. It can use a widening conversion to an int or a boxing conversion (which would be to a Short) but not both. It can therefore not convert your short to an Integer, but it can convert the short to an int, so that removes the ambiguity.

If you can't cast to a narrower type without risking truncating the stored value you can always put the varargs parameters into an array of the appropriate type, this also removes the ambiguity ie:
 
Lucien van Wouw
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks all.

Tony Docherty wrote:
If you can't cast to a narrower type without risking truncating the stored value you can always put the varargs parameters into an array of the appropriate type, this also removes the ambiguity ie:

Yes, that compiles... I assumed that this is what the compiler would do when using the comma notation.
If I remove one signature and keep signature doA(int[] i, int... args) it does precisely that in the bytecode:

And vise versa using doA(int[] i, Integer... args) {} it autoboxes the literals as:

So ok... I think I get it. The ambiguity is that declaring both signatures would offer different types that would match the caller's argument type. And the compiler has no further rules to prioritize one over the other and cannot choose an identity conversion or boxing conversion.
 
Junilu Lacar
Sheriff
Posts: 10892
158
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is all well and good from a technical curiosity point of view but what is the practical application? Seems about as useful as trying to see if you can make a car that has an extra steering wheel in the trunk. What would be the point of declaring two methods like that in the same class when just one would suffice?
 
Campbell Ritchie
Sheriff
Posts: 54078
130
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:. . . trying to see if you can make a car that has an extra steering wheel . . .
That is a really useful idea, especially for back‑seat drivers.

Well, at least as useful as those two methods
 
Paul Clapham
Sheriff
Posts: 22212
38
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You call it a "technical curiosity" but it's just the kind of question you'd find over in our Certification forums.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!