JAVA——多态之超类与子类的关系及方法调用

置换法则:

超类对象的任何地方都可以用子类对象置换。

 

一个超类变量既可以引用一个超类对象,也可以引用超类的任何一个子类的对象。如:

Manager boss = new Manager();
Employee[] staff = new Employee[3];
staff[0] = boss; 

其中Manager类为Employee的子类。这个过程也被称为向上转型,在向上转型以后,这个超类变量只能访问超类中定义的方法而不能调用子类中定义的方法,并且如果子类对这些方法进行了重写(override),则调用的是重写后的方法。为了理解虚拟机如何分辨调用哪个方法,需要理解方法调用。

方法调用:

(1)编译器查看对象的声明类型和方法名。如果要调用x.f(param)方法,编译器首先一一列举x对象所属类中名为f的方法和其父类中访问属性为public且名称为f的方法(子类不能访问超类的私有方法)。

(2)编译器查看方法调用的参数类型。这一步从各个重载(overload)的方法中找出调用的方法。但是可能子类和超类中都存在这个方法(子类继承或者重写超类的这个方法)。

(3)静态绑定或动态绑定:

如果这个方法在超类中是被private,static或者final修饰,则可以通过静态绑定判断调用哪个方法,因为这些方法都不能被子类重写(override),所以编译器可以直接判断:

①private修饰的方法被子类继承但无法直接访问,相当于对子类隐藏,因此无法被重写(override)。因此虽然可能名称和参数类型一样,但是可以把子类中的方法看成与超类中private方法无关的方法。因此编译器可以直接分辨这个方法属于哪个类(子类中有则属于子类,子类只是从超类继承则属于超类)。

②static修饰的方法可以被子类继承,但是不能被重写。与private类型修饰类似,这种同名同参数的方法可以称之为重定义,或者说被子类隐藏,但实际两个方法并没有关系。如果是子类对象,则调用的是子类的方法,如果是超类对象,则调用的是超类的方法;如果是向上转型,则调用的是超类的方法。

③final修饰的方法可以被继承,但是不能被重写,如果子类对象调用继承的final方法,实际上是调用的父类的方法。可以用final修饰方法达到关闭动态搜索的目的。在这种情况下,即使是子类对象,实际调用的还是超类的final方法。

如果不是由private、static、final修饰的方法,则编译器需要通过动态绑定判断使用哪个方法:

①虚拟机提取这个对象的实际类型的方法表,即这个对象变量(堆)指向的对象引用(栈)的类型的方法表(method table)。

②虚拟机搜索符合所调用的方法的签名的类,这时虚拟机已经知道调用哪个方法。

③虚拟机调用方法。

方法调用总结:

当没有向上转型时,若是子类中与超类中的private和static方法同名的方法,此时仍调用子类的方法(重定义,静态绑定)。

当为向上转型时,若是子类中与超类中的private和static方法同名的方法,此时调用父类中的方法(重定义,静态绑定);若没有用private或者static修饰,则调用子类中的方法(重写,动态绑定);向上转型时使用的是超类的对象变量,不能调用子类自己定义的方法。

在父类中final修饰的子类不能重写,不管有无转型都是调用父类的方法。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值