【问题标题】:Java Overload resolution - Why m(cast, cast) instead of m(match, cast)Java 重载解决 - 为什么使用 m(cast, cast) 而不是 m(match, cast)
【发布时间】:2017-07-08 12:01:13
【问题描述】:

我很确定我不会是第一个遇到这个问题的人,但我找不到答案。这是家庭作业。

class Tier{}

class Fisch extends Tier{}

class Vogel extends Tier{}

class Huhn extends Vogel{}

class Spatz extends Vogel{}

class Karpfen extends Fisch{}

class Super{
    public void m(Tier t1, Tier t2){
        System.out.println("1");
    }

    public void m(Tier t, Fisch f){
        System.out.println("2");
    }

    public void m(Fisch f, Tier t){
        System.out.println("5");
    }
}

class Sub extends Super{
    public void m(Tier t1, Fisch t2){
        System.out.println("3");
    }

    public void m(Vogel v, Fisch f){
        System.out.println("4");
    }
}


public class TierTest{
    public static void main(String[] args) {
        Tier t1 = new Tier();
        Tier t2 = new Vogel();
        Fisch f = new Karpfen();
        Vogel v1 = new Vogel();
        Vogel v2 = new Spatz();
        Huhn h = new Huhn();
        Karpfen k = new Karpfen();

        Super sup1 = new Super();
        Super sup2 = new Sub();

        sup1.m(h, v2);
        sup2.m(v1, k);   //4 expected, got 3
        sup1.m(t1, t2);
        sup1.m(v1, k);
        sup1.m(v2, f);
        sup2.m(v1, f);  //4 expected, got 3
    }
}

两次都是 Vogel(bird)(声明和运行时类型)和某种鱼。为什么选择 m(Tier, Fisch) 而不是 m(Vogel, Fisch)?

第一个参数将是一个完美的匹配。其余部分符合我的直觉。

对不起,如果我太麻木了,找不到类似的问题。

周末愉快, 斯蒂芬

【问题讨论】:

    标签: java overload-resolution


    【解决方案1】:

    这里:

    Vogel v1 = new Vogel();                
    Karpfen k = new Karpfen();
    ...
    Super sup2 = new Sub();
    ...
    sup2.m(v1, k);   //4 expected, got 3
    

    sup2 声明为 Super 类类型。
    编译器选择的方法依赖于声明变量的类,而不是运行时实例。
    因此,编译器会在 Super 类中寻找匹配的方法。

    Super 类中,这些是m() 潜在的候选方法:

    public void m(Tier t1, Tier t2){
        System.out.println("1");
    }
    
    public void m(Tier t, Fisch f){
        System.out.println("2");
    }
    
    public void m(Fisch f, Tier t){
        System.out.println("5");
    }
    

    编译器选择最具体的方法来匹配v1k 参数声明的类型:

    选择了这个方法:

    public void m(Tier t, Fisch f){
        System.out.println("2");
    }
    

    现在,在运行时,在运行时对象上调用该方法(多态原则)。
    由于sup2变量引用的运行时类是Sub,所以调用Sub的重载方法:

    public void m(Tier t1, Fisch t2){
        System.out.println("3");
    }
    

    对于第二次调用:

    sup2.m(v1, f);  //4 expected, got 3
    

    完全一样的道理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2019-06-25
      • 2014-08-18
      • 1970-01-01
      • 2017-03-06
      相关资源
      最近更新 更多