Home > Blockchain >  Why do I get an ambiguity error in this code?
Why do I get an ambiguity error in this code?

Time:01-14

Let's say we have these 3 classes:

class A { }
class B extends A { }

public class App {
    static void f(int i, A a) { }
    static void f(float j, B b) { }
   
    static public void main() {
        int i = 0;
        B b = new B();
        App.f(i, b);
    }
}

This produces the error:

App.java:11: error: reference to f is ambiguous
        App.f(i, b);
           ^
  both method f(int,A) in App and method f(float,B) in App match
1 error

Why does it not choose the type f(int, A) since i is an integer?

CodePudding user response:

It is ambiguous because of two reasons:

  • both overloads are applicable, and;
  • neither overload is more specific than the other

Notice that both the f(int, A) overload and the f(float, B) overload can be called with the parameters (i, b), since there is an implicit conversion from int to float, and an implicit conversion from B to A.

What happens when there are more than one applicable method? Java is supposed to choose the most specific method. This is described in §15.12.2.5 of the language spec. It turns out that it is not the case that one of these overloads are more specific than the other.

One applicable method m1 is more specific than another applicable method m2, for an invocation with argument expressions e1, ..., ek, if any of the following are true:

  • m2 is generic [...]

  • m2 is not generic, and m1 and m2 are applicable by strict or loose invocation, and where m1 has formal parameter types S1, ..., Sn and m2 has formal parameter types T1, ..., Tn, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ n, n = k).

  • m2 is not generic, and m1 and m2 are applicable by variable arity invocation [...]

Only the second point applies to the two overloads of f. For one of the overloads to be more specific than the other, every parameter type of one overload has to be more specific than the corresponding parameter type in the other overload.

A type S is more specific than a type T for any expression if S <: T (§4.10).

Note that"<:" is the subtyping relationship. B is clearly a subtype of A. float is actually a supertype (not subtype!) of int. This can be derived from the direct subtyping relations listed in §4.10.1. Therefore, neither of the overloads is more specific than the other.

The language spec goes on to talk about maximally specific methods, which doesn't really apply to f here. Finally, it says:

Otherwise, the method invocation is ambiguous, and a compile-time error occurs.

More Examples

static void f(int x) {}
static void f(float x) {}

when called with an int are not ambiguous because the int overload is more specific.

static void f(int x, B a) {}
static void f(float x, A a) {}

when called with argument types (int, A) are not ambiguous because the (int, B) overload is more specific.

static void f(int x, A a) {}
static void f(float x, A a) {}

when called with argument types(int, A) are not ambiguous because the (int, A) overload is more specific. Note that the subtyping relationship is reflexive (i.e. A is a subtype of A).

CodePudding user response:

Note that for calling an overloaded method in java :

Priority Order for Primitive types:

Same type > Auto Widening > Boxing > Upcasting(Parent Class) > Super Class

Priority Order for Reference types:

Same type > Upcasting(Parent Class) > Super Class > Unboxing

Explanation :

    // you have here a method who accept an int = same Type 
    //  f(int i, A a) { } and this method can accept the other parameter 
    //  because B is a subclass of A
    int i = 0;
    // But You have a method who accept a B reference = same Type 
    // f(float j, B b) { } and this method can accept the other parameter 
    // because float is actually a supertype of int as mentionned by Sweeper
    B b = new B();

 // So calling the method with an int and a B reference 
 // will confuse the compiler because both of the two methods
 // can accept the other parameter
    App.f(i, b);
  •  Tags:  
  • Related