• Java继承中的多态


    Java中有两种形式可以实现多态:继承和接口,本文关注继承。

    继承中多态只是实例方法的多态,属性和静态方法不适用多态。或者说实例方法是动态绑定的,静态方法和成员变量是静态绑定的。

    1.实例方法

    class Base{
       void method(){
           System.out.println("Base method!");
        }
    }
    
    class Sub extends Base{
        void method(){
            System.out.println("Sub method!");
            System.out.println(var);
        }
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Base who = new Sub();
            who.method();
        }
    }

    结果

    Sub method!

    Java中只有private、static和final修饰的方法以及构造方法是静态绑定。

    a、private方法的特点是不能被继承,也就是不存在调用其子类的对象,只能调用对象自身,因此private方法和定义该方法的类绑定在一起。
     
    b、static方法又称类方法,类方法属于类文件。它不依赖对象而存在,在调用的时候就已经知道是哪个类的,所以是类方法是属于静态绑定。
     
    c、final方法:final方法可以被继承,但是不能被重写,所以也就是说final方法是属于静态绑定的,因为调用的方法是一样的。
     总结:如果一个方法不可被继承或者继承后不可被覆盖,那么这个方法就采用的静态绑定。

    2.成员变量

    class Base{
        String var = "Base var";
    }
    
    class Sub extends Base{
        String var = "Sub var";
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Base who = new Sub();
            System.out.println(who.var);
        }
    }

    结果

    Base var

    3.实例方法的多态是个例外。对于一个引用类型的变量,Java编译器按照它的声明的类型来处理,一个父类类型的变量引用了子类实例,该变量不会主动转为子类。

    声明的类型并非实际的类型

    class Base{
    
    }
    
    class Sub extends Base{
    
        String subVar = "Sub var";
        void subMethod(){
            System.out.println("Sub submethod!");
        }
    
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Base who = new Sub();
    
            who.subMethod(); X
            who.subVar; X
    
        }

    who是Base类型,根本就没有subMethod()方法和subVar属性,直接报错。

    因此,最开始提到的1.实例方法(成员方法)的多态,其前提条件就是,子类的这个方法在父类中也有,即父类方法被重写了。

    因此,在 被调用方法在父类中声明,也就是说被子类覆盖的方法 的前提之下,父类变量指向子类的引用,优先调用子类(实际类型)的方法,子类找不到在父类中找。这也是多态实现的另一种说法或原因。

    class Base{
        void method(){
           System.out.println("Base method!");
        }
    }
    
    class Sub extends Base{
    
    }
    
    public class Test {
    
        public static void main(String[] args) {
            Base who = new Sub();
            who.method();
    
        }

    当虚拟机创建子类的时候,会创建该子类的方法列表,同时包含父类的方法列表。同时虚拟机会参数引用的实际地址,找到创建的这个子类对象,查询方法列表,如果在子类对象中找到这个方法,就直接调用。

    如果没找到,就去查询父类方法,调用父类的方法。

    子类继承了父类,获得了父类的属性和方法?应是,子类中有父类对象(子类的初始化会引发父类的初始化,当然这须在父类未被初始会之时),子类中super()可以构造父类,子类可以调用父类中的方法,即对方法有使用权,并非真实拥有,即所有权。

     

  • 相关阅读:
    Meterpreter核心命令
    bugku ctf 杂项 旋转跳跃 (熟悉的声音中貌似又隐藏着啥,key:syclovergeek)
    bugku 神秘的文件
    代码审计
    “百度杯”CTF比赛 九月场 类型:Web 题目名称:SQLi ---不需要逗号的注入技巧
    热烈祝贺北亚获批电子数据司法鉴定执业资格!
    硬盘有坏道的表现和避免硬盘坏道的方法
    如何应对eva存储崩溃的情况?
    linux系统数据恢复过程
    DELL EqualLogic PS6100恢复数据原理概述
  • 原文地址:https://www.cnblogs.com/aidata/p/13659040.html
Copyright © 2020-2023  润新知