方法模糊不清 - 为什么不解决

时间:2014-03-01 20:29:55

标签: java

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);
}

编译器说Hungry(Mamal)的方法含糊不清。 我希望执行“人类”方法,因为它是最低级别。我没有从http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12

中找到歧义的原因

3 个答案:

答案 0 :(得分:11)

HumanBird在继承层次结构中处于同一级别(尽管不是在视觉上)。或者将它们视为完全不相关的引用类型。因此,一个并不比另一个更具体。

如果删除Hungry(Bird)方法,则代码将编译。

更具体的规则是here

  

一个名为m的固定成员方法比另一个更具体   如果以下所有内容的同名成员方法和arity   条件成立:

     
      
  • 第一个成员方法的参数的声明类型是   T1,...,Tn。

  •   
  • 其他方法的参数的声明类型是U1,...,   未

  •   
  • 如果第二种方法是通用的,那么让R1 ... Rp(p≥1)为其   类型参数,设B1为Rl的声明边界(1≤l≤p),let   A1 ... Ap是推断的类型参数(第15.12.2.7节)   在初始约束条件下调用Ti<< Ui(1≤i≤n),让   Si = Ui [R1 = A1,...,Rp = Ap](1≤i≤n)。

  •   
  • 否则,让Si = Ui(1≤i≤n)。

  •   
  • 对于从1到n的所有j,Tj&lt ;: Sj。

  •   
  • 如果第二种方法是如上所述的通用方法,那么Al   <:Bl [R1 = A1,...,Rp = Ap](1≤l≤p)。

  •   

所以你有

public void Hungry(Human human){
    System.out.println("Human");        
}
public void Hungry(Bird bird){
    System.out.println("Bird");
}

因此HumanT1BirdU1(也会尝试相反)。方法不通用。

S1 = U1

对于从i到n(1到1)的所有j,这应该成立:Ti <: Si,其中<:

  

我们写T&lt;:S表示子类型关系在类型T和S之间成立。

这不适用于我们的两种方法,因为Human不是Bird的子类型,反之亦然,因此没有更具体的方法来调用,即。歧义。

就像你有

一样
void method(String s){}
void method(RandomReferenceType t) {}

并试图致电

method(null);

答案 1 :(得分:2)

由于null没有与之关联的类型,编译器不知道应该调用哪个hungry方法;因此,它是不明确的&#34;。要消除它的歧义,只需投下它:

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 {}

答案 2 :(得分:2)

amibuity是因为您有三个具有相同名称的方法,并且您传递的是null值。编译器不知道您调用的是哪种方法。只需写一个ie public void hungry(Animal animal)并检查里面动物的类型。例如if(animal instanceof Bird) { System.out.println("Bird") ....。 还要将方法名称更改为小写。有时编译器会失败。