Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

446
Views
Why do I get an ambiguity error in this code?

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?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

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).

over 4 years ago · Santiago Trujillo Report

0

Two things:

  • Type widening (1st parameter)
  • Inheritance (2nd parameter)

Type widening: float is "wider" type than int therefore passed int value can be easily packed into bigger float box. It will not work in case, when we would like to "pack" float into int, as we can potentially lost floating point. In provided case, having an int we can potentially pass it two both functions.

fFloat(float f){}
int intValue = 221;
fFloat(intValue); // inside f, intValue is treated as 221.0

fInt(int i){}
float floatVal = 221.221;
fInt(floatVal); // what should compiler do with remaining .221 part?

Inheritance: A is a base class, while B is one of subclasses of A. So, when we declare method parameter as a base class, we can provide there both base class and its instance (but we will be able to use B b instance inside f(int i, A a) like type A. Hence, we can pass B b = new B(); to both methods as well.

class A {
public void f() {}
}

class B extends A {
public void g() {}
}

fA(A a){}
B bInst = new B();
fA(bInst); // you can refer only to f() method, not g()

fB(B b){}
A aInst = new A();
fB(aInst); // you cannot do this, as subclass can have some additional
// stuff, that superclass does not have

//but even
A aInstBImpl = new B();
fB(aInstBImpl); // will not work without explicit casting as it is
// kind of A instance with B implementation - here polymorphism comes into action

Since all 2 parameters (from 2 possible) can suit to both methods without any explicit "action taken", the ambiguity error arises.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!