美文网首页
重识Java多态

重识Java多态

作者: r09er | 来源:发表于2018-03-24 23:40 被阅读83次

    今天面试被问到了Java多态的知识点

    面试官:  了解多态吗,说一说你对多态的理解

    我: balabala..

    面试官: 知道多态是如何实现的吗

    我: 涉及到了我的知识盲区...

    赶紧回去拿起Thinking In Java看一遍多态的章节..

    作为面向对象中的一个重要特征,多态的原理必须要掌握.
    多态:

    多态通过分离做什么怎么做,从另一个角度将接口和实现分离开来,多态不但能够改善代码的组织结构和可读性,还能创建可拓展的程序.

      多态也被称为动态绑定,后期绑定或运行时绑定.

    方法调用绑定

    在考虑这个问题之前先看一段代码

    public enum Note {
        MIDDLE_C, C_SHARP, B_FLAT;
    }
    
    public class Instrument {
        public void play(Note note) {
            System.out.println("Instrument.play()");
        }
    }
    
    public class Wind extends Instrument {
        @Override
        public void play(Note note) {
            System.out.println("Wind.play()" + note);
        }
    }
    
    public class Bass extends Instrument {
        @Override
        public void play(Note note) {
            System.out.println("Bass.play*() " + note);
        }
    }
    
    
    public class Music {
        private static void tune(Instrument instrument) {
            instrument.play(Note.MIDDLE_C);
        }
        public static void main(String[] args) {
            Wind wind = new Wind();
            Bass bass = new Bass();
            tune(wind);
            tune(bass);
        }
    }
    

    这段代码就是典型的多态运用,面向抽象和基类编程,依赖于抽象和基类,而不是依赖于具体实现.

    private static void tune(Instrument instrument) {
            instrument.play(Note.MIDDLE_C);
    }
    

    在tune方法中,接收一个Instrument对象,在这种情况下,编译器是如何知道Instrument引用指向Wind对象还是Bass呢?实际上编译期是无法得知的.

    那要如何正确引用正确的对象呢?

    解决办法就是通过对象的后期绑定,在运行时根据对象的类型进行绑定.

    后期绑定也称为动态绑定或者运行时绑定,Java中除了static方法和final方法外,其他所有的方法都是后期绑定.意味着无需判定是否进行后期绑定--因为会自动发生.

    可拓展性

    回到开始的代码示例,由于有多态机制,所以可以根据自己的需要对系统添加任意多的新类型,而不需要改变tune方法中参数的引用类型.这样的程序就是可扩展的.

    这就是面向基类和面向抽象编程的重要意义.

    缺陷
    直接访问域对象,这个访问在编译期就会进行解析

    示例中,子父类拥有一样的成员变量

    public class FieldTest {
        public int num =10;
        public int getNum() {
            return num;
        }
    }
    
    public class FieldSubTest extends FieldTest{
        public int num = 20;
        @Override
        public int getNum() {
            return num;
        }
        public int getSuper(){
            return super.num;
        }
    }
    
    public class TestMain {
        public static void main(String[] args) {
            FieldTest fieldTest = new FieldSubTest();
            System.out.println(fieldTest.num+"----"+fieldTest.getNum());
            FieldSubTest fieldSubTest = new FieldSubTest();
            System.out.println(fieldSubTest.num+"----"+fieldSubTest.getNum()+"----"+fieldSubTest.getSuper());
        }
    }
    

    运行结果

    10----20
    20----20----10
    

    产生这样结果的原因就在于所有的域访问操作(直接访问public修饰的成员变量),将有编译期进行解析,因此不是多态的.

    但是开发中一般不会这样操作,一般都会通过方法对变量进行访问.

    如果方法是静态的,它的行为就不具有多态性.

    静态方法是与类,而不是与单个对象相关联的.

    协变返回类型

    在JavaSE5.0开始,允许方法返回对象的基类.

    其余特点与注意

    多态还有不少需要注意的地方,例如向下转型,通过组合代替继承等,需要更加多编程经验才能真正掌握多态的意义和灵活使用的方法.

    相关文章

      网友评论

          本文标题:重识Java多态

          本文链接:https://www.haomeiwen.com/subject/irgccftx.html