java - 为什么JVM会在继承树中寻找从子到父的方法?
问题描述
这是我正在查看的示例代码,并且想知道为什么当父类中存在类似方法并且引用类型为父类但对象类型为时,JVM 总是在子类中查找方法孩子。
class A{
public void saveLink(){
System.out.println("A: saveLink");
bookmark();
}
public void bookmark() {
System.out.println("A: bookmark");
}
}
class B extends A{
public void bookmark(){
System.out.println("B: bookmark");
}
}
class C extends B{
}
class Test {
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
c.saveLink();
}
}
当我运行上面的代码时,它输出:
A: saveLink
B: bookmark
有人可以解释一下吗?
解决方案
这是在 Java 中实现多态的方式之一。它被称为动态绑定。
在运行时执行的实现是通过查看调用方法的对象的实际类来确定的。
在您的情况下,当您声明A b = new B();
然后调用b.bookmark()
时,Java首先查看运行时,对象的实际类型(B
是创建对象时使用的运行时类型new B()
),而不管其静态或声明类型(即,不管声明的指向对象的变量的类型)。
当 Java 发现该方法已在运行时类中被覆盖时(b
您的示例中的 object 就是这种情况),它会执行该实现。否则,它会沿着类层次结构查找继承的实现,正如您所指出的(c
您的示例中的 object 就是这种情况)。
请注意:
- 此行为仅适用于实例方法(它不适用于静态方法或字段)。静态方法是根据声明的/静态类型选择的。
- 有一个例外(我能想到):当调用完成时
super.bookmark()
,Java 必然会运行超类的实现——这不是您的示例中的场景。
推荐阅读
- node.js - 如何修复此节点控制器功能并从 2 个不同模型发送数据?
- unity3d - 有没有办法读取围绕局部轴的旋转?
- python-3.x - Why my console application is buffering log and socket messages?
- php - 如何根据 IIS windows 身份验证过滤 ldap 活动目录用户信息并在 php 网站中显示该信息?
- android - 如何修复错误:无法确定 com.github.apl-devs:appintro:v4.2.3 的工件:由于早期错误而跳过
- javascript - 使用 Lodash 将对象键转换为具有键值的数组
- vb6 - Windows 更新后 Webbrowser 控件不再工作
- android - 如何访问 src 包中的阴影文件级属性
- go - 将 Go 微服务保存在 Github 上的不同存储库中
- ruby - sinatra-cors 在使用中间件时没有响应 200