关于多态的一些学习感悟

来源:互联网 发布:剑三霸刀捏脸数据 编辑:程序博客网 时间:2024/06/10 11:40

今天,看了java编程思想以后,对多态又有了一些新的感悟,在这里和大家分享学习。

多态也称为动态绑定、后期绑定或运行时绑定。java中的所有方法都是通过动态绑定实现多态的。


可能有点迷糊,代码可能比较直观

package cn.bababa;class Instrument{public void play() {System.out.println("instrument.play()");}}class Wind extends Instrument{public void play() {System.out.println("wind.play()");}}public class Music{public static void tune(Instrument i) {i.play();}public static void main(String[] args) {Wind flute = new Wind();tune(flute);}}
结果:wind.play()
如上图代码,tune方法,它接受一个Instrument引用,那么在这种情况下,编译器怎么才能知道这个Instrument引用指向的是Wind对象,而不是Brass对象或其他呢?

实际上,编译器无法得知,研究这个必须先说一个概念。

什么是绑定?

讲一个方法调用同一个方法主体关联起来被称为绑定。若在程序执行前进行绑定(由编译器实现)叫做前期绑定。而当编译器只有一个Instrument引用时,它无法知道究竟调用的的哪个方法才对。解决的方法就是后期绑定:就是在运行时根据对象的类型进行绑定。也就是说编译器使用不知道对象类型,但是方法调用机制能找到正确的方法体,并加以调用。

         Java中除了static和final方法(private方法属于final方法)之外,其他的所有方法都是后期绑定。

上图可能有人会问,为什么不在main(主函数)中,直接写Instrument i = new Wind();i.play();其实结果是一样的,只是那样写比较直观(其实是书上这样写的偷笑


可能你很久很久以前就了解了多态的机制,可能就会开始认为所有事物都可以多态的发生。然而,只有普通的方法调用可以是多态的。

例如:如果你直接访问某个域,这个访问就将在编译期进行解析,就像下面的示例所演示这样。

要颠覆你的三观了,我是被教育了,真的...很严肃

package cn.bababa;class Super{public int field = 0;public int getField() {return field;}}class Sub extends Super{public int field = 1;public int getField() {return field;}public int getSuperField() {return super.field;}}public class FieldAccess{public static void main(String[] args) {Super sup = new Sub();System.out.println("sup.field = "+sup.field+", sup.getField() = "+sup.getField());Sub sub = new Sub();System.out.println("sub.field = "+sub.field+", sub.getField() = "+sub.getField()+", sub.getSuperField() = "+sub.getSuperField());}}
结果:sup.field = 0, sup.getField() = 1sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0

当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态。在本例中,为Super.field和Sub.field分配了不同的存储空间(就针对Super sup = new Sub()这一句来说,先生成了Sub对象,再将他的引用向上转型为Super对象)。这样,sub实际上包含两个称为field的域:它自己的和它从super处得到的。然而,在引用sub中的field时所产生的默认域并非super版本的field域。因此,为了得到super.field,必须显示地指明super.field。如果某个方法是静态的,它的行为也不具有多态性。因为静态方法是与类相关联,而非与单个对象相关联。

域:你可以理解为变量(lz个人理解)


当你看到这里并且充分理解,恭喜你,又进步了一毫米,后面可能会陆续更新一些java基础的知识,和大家分享,楼主最近正在以龟速爬java编思,回头见!