java面试题——对于多态你是怎么理解的呢?不一样的角度,带你重新看java
java面试的时候经常会被问到一个问题,那就是java三大特性:继承,封装和多态。那么这三者的含义究竟是什么你真的清楚吗?我看网上大多都是人云亦云。所以我想把我的想法记录下来供大家参考~今天先聊一个,多态是什么呢?
我们都知道,java程序是分为编译和运行两部分的,那你有没有想过,java的编译的期间是怎么判断你所写的方法是属于哪里的呢?没错,就是我们常说的绑定。绑定就是指把一个方法和方法的主体关联起来,对于java来说,绑定分为静态绑定和动态绑定。那这和我们的多态有什么关系呢!所谓的多态,就是指父类引用指向子类对象,这样调用的方法就是子类的实现而不是父类的实现,多态实现的核心就是我们上面说的动态绑定。这样说是不是有点迷?没事,往下看就知道了。
首先说一下静态绑定:java程序运行前就可以知道这个方法所属的主体,实际上也就是java程序编译期间的绑定,java中的方法只有用private,final,static和构造方法是静态绑定。那么我们来回忆一下这几个东西的特点:
private修饰的方法,不可以在子类当中被继承,所以自然也就和本类绑定到了一起。
final修饰的方法,可以被继承,但是不可以被覆盖(重写),所以子类调用的都是父类当中的这个final方法,所以我们也可以了解到final 的作用:一,防止方法被覆盖,二,有效的关闭动态绑定。
构造方法这个也不用多说,虽然网上有说继承这个类就默认继承了他的无参构造,但是我们都知道super关键字就是帮助子类调用父类的构造方法来实现初始化,而我们使用继承的方法则不需要那么做,所以编译器也可以看出这个方法的主体。
static修饰的方法,可以被继承,但是不可以被覆盖,但是可以被子类隐藏。继承自然是指这个方法可以继承父类的静态方法,但是不能够重写,如果子类中有相同的方法时,父类的方法被隐藏起来,为什么这么说呢?因为如果将子类转型向上为父类时,那么调用该方法时使用的是父类的方法,所以是被隐藏起来。
说完了静态绑定,我们说一下重要的动态绑定,那么如果一个方法在编译期间没办法判定方法的主体怎么办,那就需要我们的动态绑定,也就是运行期间的绑定。是如何实现的呢?不同的语言动态绑定的方法是不一样的,Java是什么样的呢?首先虚拟机提取对象实际类型的方法表,虚拟机查找方法签名,调用该方法。因此当虚拟机调用一个实例方法时,就会根据对象的实际的类型来选择相应的方法,这也就是我们所说的动态绑定。多态的实现方式,比如接口,重写或者抽象类和抽象方法都是基于这一个中心思想来实现的。
综上,大家可以思考一下,成员变量或者类变量采用的是什么绑定呢?有没有什么办法可以使得静态绑定变为动态绑定呢?