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

报告相同问题?

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型