Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler error : reference to call ambiguous

Tags:

Case 1

static void call(Integer i) {     System.out.println("hi" + i); }  static void call(int i) {     System.out.println("hello" + i); }  public static void main(String... args) {     call(10); } 

Output of Case 1 : hello10

Case 2

static void call(Integer... i) {     System.out.println("hi" + i); }  static void call(int... i) {     System.out.println("hello" + i); }  public static void main(String... args) {     call(10); } 

Shows compilation error reference to call ambiguous. But, I was unable to understand. Why ? But, when I commented out any of the call() methods from Case 2, then It works fine. Can anyone help me to understand, what is happening here ?

like image 935
Ravi Avatar asked Dec 27 '12 11:12

Ravi


People also ask

What is an ambiguity error?

Ambiguity errors occur when erasure causes two seemingly distinct generic declarations to resolve to the same erased type, causing a conflict.

What is an ambiguous function call?

You cannot override one virtual function with two or more ambiguous virtual functions. This can happen in a derived class that inherits from two nonvirtual bases that are derived from a virtual base class.

What is ambiguous reference in C++?

Access to a base class member is ambiguous if you use a name or qualified name that does not refer to a unique function or object. The declaration of a member with an ambiguous name in a derived class is not an error. The ambiguity is only flagged as an error if you use the ambiguous member name.

What is ambiguous method call in Java?

This ambiguous method call error always comes with method overloading where compiler fails to find out which of the overloaded method should be used.


1 Answers

Finding the most specific method is defined in a very formal way in the Java Language Specificaion (JLS). I have extracted below the main items that apply while trying to remove the formal formulae as much as possible.

In summary the main items that apply to your questions are:

  • JLS 15.12.2: your use case falls under phase 3:

The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

  • Then JLS 15.12.2.4 basically determines that both method are applicable, because 10 can be converted to both an Integer... or an int.... So far so good. And the paragraph concludes:

The most specific method (§15.12.2.5) is chosen among the applicable variable-arity methods.

  • Which brings us to JLS 15.12.2.5. This paragraph gives the conditions under which an arity method m(a...) is more specific than another arity method m(b...). In your use case with one parameter and no generics, it boils down to:

m(a...) is more specific than m(b...) iif a <: b, where <: means is a subtype of.

It happens that int is not a subtype of Integer and Integer is not a subtype of int.

To use the JLS language, both call methods are therefore maximally specific (no method is more specific than the other). In this case, the same paragraph concludes:

  • If all the maximally specific methods have override-equivalent (§8.4.2) signatures [...] => not your case as no generics are involved and Integer and int are different parameters
  • Otherwise, we say that the method invocation is ambiguous, and a compile-time error occurs.

NOTE

If you replaced Integer... by long... for example, you would have int <: long and the most specific method would be call(int...)*.
Similarly, if you replaced int... by Number..., the call(Integer...) method would be the most specific.

*There was actually a bug in JDKs prior to Java 7 that would show an ambiguous call in that situation.

like image 91
assylias Avatar answered Oct 12 '22 12:10

assylias