天天看点

java核心技术学习笔记7---继承与多态

多态是OOP继抽象、封装、继承后的又一基本特性。我们把在Java中的多态性概括到方法多态上。而这种方法的多态性又分为编译时多态(编译期绑定、前期绑定、静态绑定)和运行时多态(运行时绑定、后期绑定、动态绑定)。

编译时多态

编译期多态主要体现在类的重载。

 在一个类中声明多个同名方法,但方法的参数列表不同。称为方法重载。

方法重载不分实例方法还是静态方法。也就是说,一个实例方法的名称及参数列表与本类中一个静态方法的名称及参数列表一样是不可以的。在声明方法时,重载多态性是看不出来的。只有在调用时,你才会感觉象是一个方法有不同的形态(可以使用不同的参数调用)。其实我们声明了多个方法。编译器区别方法的方式是方法名称及参数列表,而不只是方法名称。

所谓绑定就是将一个方法调用与一个方法主体(方法声明的方法体)联系起来。而编译期绑定是在编译期就可以决定下来的绑定。那就是方法重载。编译器可以把方法调用处标记为“调用符号为XXX的方法”的字节码,而在方法声明处标记为“符号为XXX的方法”。这时已经完成了绑定动作。

运行时多态

运行时多态主要体现在继承中子类对父类方法的重写(覆盖)上。

方法覆盖的特性与方法重载不同,覆盖是指,在子类中重写父类中已有的实例方法。

覆盖的语法要求:

1) 父类中已有方法。

2)父类中使用private、static或final修饰的方法不能覆盖。就算你在子类中重写了以上方法也不会真的产生覆盖效果。

3) 覆盖方法要求方法的返回值类型、方法名称、方法参数列表必须于父类中被覆盖方法相同。

4) 覆盖方法要求访问级别只能更宽松,而不能更严格。例如父类方法的访问级别为protected,那么子类方法只能是protected或public,而不能是默认或private。

5) 覆盖方法要求声明的异常只能等于或少于父类方法声明的异常。

编译器调用方法过程

1)编译器查看对象的声明类型和方法名。假设调用x.f(Param),且x被声明为C类的对象。编译器会一一列举所有C类中名为f的所有方法和其超类中访问属性为public且名为f的方法。

2)得到所有候选方法后,编译器将查看调用方法时提供的参数类型。如果在所有方法名为f的方法中存在一个参数类型与提供的参数完全匹配,则直接调用该方法,这个过程被称为“重载解析”(overloading resolution),若没找到与参数类型匹配的方法,或者发现经过类型转换后有多个方法与之匹配,则报错。

3)如果方法是private,static ,final或者构造器,那么编译器可以准确的指导应该调用哪个方法,这种方式称为“静态绑定”(static binding)。

4)若调用方法依赖于隐式参数的实际类型,采用动态绑定方式调用方法,虚拟机一定调用与x所引用的对象的实际类型最合适的那个方法。若x的实际类型为D类,它是C类的子类。如果D类定义了方法f(Stirng),就调用它,否则,再在D类的父类中寻找方法f(String)以此类推。