标签: #Java
日期:2021/3/26
在《Thinking In Java》一书中,作者将多态称作动态绑定、后期绑定或运行时绑定。
直白的讲就是将一个由子类B创建的对象的引用b赋给一个父类A创建的变量a(A a = new B();
),此时用a变量调用一个A、B两个类都存在的方法f()
,即a.f()
,则此时实际调用的是B.f()
,即B类中的方法。下面给出一段伪代码能更清晰的描述上面这段话:
class Employee{
// param表示参数
public void work(){
print("Employee work");
}
}
class Manager extends Employee{
// 覆写父类中的work()方法
public void work(){
print("Manager work")
}
}
public class Test{
public static void main(Stirng... args){
Employee e = new Manager(); // 向上转型
e.work();
}
}
//output:
Manager work
上面这段代码就体现出了Java的多态特性,一个Employee变量既可以引用一个Employee类对象,也可以引用一个Employee类的任何一个子类的对象(例如Manager)
Java是怎样确定e.work(param)
调用Employee.work(param)
还是Manager.work(param)
呢?即怎样确定是调用子类的方法还是父类的方法。
将一个方法调用同一个方法主体关联起来被称作绑定,即确定e.work(param)
调用的是哪一个方法。
在编程语言中,有两种绑定方式——前期绑定和后期绑定
若在程序执行前进行绑定(由编译器绑定),叫做前期绑定,如面向过程的C语言。
若在运行时根据对象的类型进行绑定,叫做后期绑定(也被称为运行时绑定或动态绑定)。
在Java中,除了static方法、final方法和private方法之外其他所有的方法都是后期绑定。
在程序运行时,虚拟机一定调用与e所引用对象的实际类型最合适的那个类的方法。例如e的实际类型是Manager,如果Manager中存在e要调用的方法则就直接调用它,如果不存在就在父类Employee中寻找,这个寻找的过程是在继承树中是由下向上的。
在《Java核心技术 卷Ⅰ》中的5.1.6 理解方法调用,有更加详细的解释,感兴趣的可以翻阅。
其实应该多去学习更加原始的知识,而不能总是依靠博客中经过别人加工的知识。记得王小波的书里有一段话:
据我所见,诀窍和真正的知识是不同的。真正的知识不仅能说明一件事情应该怎样做,还能说明为什么要这样做。而那些诀窍呢,从来就说不出为什么,所以是靠不住的。能使人变聪明的诀窍是没有的。倒是有种诀窍能使人觉得自己变聪明了,实际上却变得更笨。
有些博客就像王小波所说的诀窍,而专业的书籍就像知识,掌握些诀窍可能会使你在短期内突飞猛进,让你觉得好像什么都毁了,好像是变聪明了,但却都不是真正的知识。就长期来看,还是应该学习些真实的知识,而不是别人的诀窍,但是也不能激烈的排斥诀窍,将两者结合起来,可能效果更好。
原文:https://www.cnblogs.com/winslow/p/14584744.html