public class Animal {}
public class Bird extends Animal {}
public class Mamal extends Animal {}
public class Human extends Mamal {}
public class Main {
public void Hungry(Mamal mamal){
System.out.println("Mammal");
}
public void Hungry(Human human){
System.out.println("Human");
}
public void Hungry(Bird bird){
System.out.println("Bird");
}
public static void main(String a[]){
Main main = new Main();
main.Hungry(null);
}
Compiler says The method Hungry(Mamal) is ambiguous. I would expect to execute the "Human" method as it is the lowest level. I failed to find the reason for ambiguity from http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12
Human
and Bird
are at the same level in the inheritance hierarchy (not visually though). Or think of them as completely unrelated reference types. Therefore one isn't more specific than the other.
If you remove the Hungry(Bird)
method, your code will compile.
The rules for more specific are here.
One fixed-arity member method named m is more specific than another member method of the same name and arity if all of the following conditions hold:
The declared types of the parameters of the first member method are T1, ..., Tn.
The declared types of the parameters of the other method are U1, ..., Un.
If the second method is generic, then let R1 ... Rp (p ≥ 1) be its type parameters, let Bl be the declared bound of Rl (1 ≤ l ≤ p), let A1 ... Ap be the type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ti << Ui (1 ≤ i ≤ n), and let Si = Ui[R1=A1,...,Rp=Ap] (1 ≤ i ≤ n).
Otherwise, let Si = Ui (1 ≤ i ≤ n).
For all j from 1 to n, Tj <: Sj.
If the second method is a generic method as described above, then Al <: Bl[R1=A1,...,Rp=Ap] (1 ≤ l ≤ p).
So you have
public void Hungry(Human human){
System.out.println("Human");
}
public void Hungry(Bird bird){
System.out.println("Bird");
}
So Human
is T1
and Bird
is U1
(the reverse is also attempted). Methods are not generic.
S1 = U1
For all j
from i to n (1 to 1), this should hold: Ti <: Si
, where <:
is
We write T <: S to indicate that that the subtype relation holds between types T and S.
This doesn't hold for our two methods as Human
is not a sub type of Bird
and vice versa, so there is no more specific method to call, ie. ambiguity.
It's the same as if you had
void method(String s){}
void method(RandomReferenceType t) {}
and tried to call
method(null);
The amibuity is because you have three methods with same name and you are passing a null value. The compiler doesn't know which method you are calling. Just write one ie public void hungry(Animal animal)
and check the type of the animal inside. For example if(animal instanceof Bird) { System.out.println("Bird") ....
.
Also change the method names to lowercase. Sometimes the compiler will fail.
Since null
does not have a type associated with it, the compiler does not know which of your hungry
methods should be invoked; therefore, it's "ambiguous". To disambiguate it, simply cast it:
public class Main {
public void hungry(Mamal mamal){
System.out.println("Mammal");
}
public void hungry(Human human){
System.out.println("Human");
}
public void hungry(Bird bird){
System.out.println("Bird");
}
public static void main(String a[]){
Main main = new Main();
main.hungry((Mamal)null);
}
}
class Animal {}
class Bird extends Animal {}
class Mamal extends Animal {}
class Human extends Mamal {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With