ndsc-account 2020-01-13 01:27 采纳率: 100%
浏览 443
已采纳

Java中指向子类的父类对象调用子类重载的方法,传入指向子类对象的父类引用,为什么最终还是调用了父类的方法?

Dog类实现了Animal接口,Animal a = new Dog(); 创建子类对象,a指向的应该是一个Dog类的对象,a.bark(d); 调用的应该是Dog重载的bark方法才对,可为什么最终调用的还是接口Animal的方法呢。

public interface Animal {
    default void bark(Animal a) {
        System.out.println("Animal");
    }
}

public class Dog implements Animal {
    // Overload
    public void bark(Dog d) {
        System.out.println("Dog");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog();
        Dog d = new Dog();
        a.bark(a); // Animal
        a.bark(d); // Animal

        d.bark(a); // Animal
        d.bark(d); // Dog
    }
}
  • 写回答

6条回答 默认 最新

  • 关注
    1. a是一个Animal类型引用,调用方法时,编译器会先去Animal类中的虚函数表中找有没有可以调用的方法。编译器找到Animal中的bark方法,而bark并没有被Dog实现,且Animal中的bark方法参数类型为Animal,而Dog为Animal的实现类,所以函数可以使用,于是编译器偷了个懒就不去Animal类的虚函数表中去匹配方法了,所以a.bark(d),调用的是接口中的方法。

    2. 而d是一个Dog类型引用。编译器会先去Dog类的虚函数表中找有没有可以调用的方法,找到Dog中的bark方法和Animal中的bark方法,因为参数d为Dog类型,固根据参数匹配原则选择Dog类中的bark方法。

    3. 总的来说,接口类型的引用,优先使用接口中没被实现且可以用的方法。在Animal类的虚函数表中,只有Animal的bark方法地址,没有Dog中的bark方法地址。

    4. 深究可以去看看虚函数表,不过这个概念只在C++中存在,而java和C++本是同根生。

    5. 原创手打,忘采纳。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题