前言: 类的继承性是面向对象语言的基本特性,多态性的前提是继承性。Java支持继承性和多态性。本文章续写java的多态性。
在面向对象程序设计中多态是一个非常重要的特性,理解多态有利于进行面向对象的分析与设计。
1, 多态概念
发生多态要有三个前提条件:
- 继承。多态发生一定要子类和父类之间。
- 覆盖。子类覆盖了父类的方法。
- 声明的变量类型是父类类型,但实例则指向子类实例。
下面通过一个示例理解什么是多态。如下图所示,父类Figure(几何图形)类有一个onDraw()绘图)方法,Figure(几何图形)它有两个子类Ellipse(椭圆形)和Triangle(三角形),Ellipse和Triangle覆盖onDraw方法。Ellipse和Triangle都有onDraw方法,但具体实现的方式不同
具体代码如下:
调用代码如下:
上述带代码第②行和第③行是符合多态的三个前提,因此会发生多态。而代码第①行和第④行都不符合,没有发生多态。
运行结果如下:
从运行结果可知,多态发生时,Java虚拟机运行时根据引用变量指向的实例调用它的方法,而不是根据引用变量的类型调用。
2 引用类型检查
有时候需要在运行时判断一个对象是否属于某个引用类型,这时可以使用instanceof运算符,instanceof运算符语法格式如下:
其中obj是一个对象,type是引用类型,如果obj对象是type引用类型实例则返回true,否则false。
为了介绍引用类型检查,先看一个示例,如图所示的类图,展示了继承层次树,Person类是根类,Student是Person的直接子类,Worker是Person的直接子类在这里插入图片描述
调用代码:
调用代码:
上述代码第①行和第②行创建了3个Student实例,代码第③行和第④行创建了两个Worker实例,然后程序把这5个实例放入people数组中。
代码第⑥行使用for-each遍历people数组集合,当从people数组中取出元素时,元素类型是People类型,但是实例不知道是哪个子类(Student和Worker)实例。代码第⑦行item instanceof Worker表达式是判断数组中的元素是否是Worker实例;类似地,第⑧行item instanceof Student表达式是判断数组中的元素是否是Student实例。
结果如下 :
工人人数:2, 学生人数:3
3,引用类型转换
众所周知,数值类型相互转换,引用类型可以进行转换,,但并不是所有的引用类型都能互相转换,只有属于同一棵继承层次树中的引用类型才可以转换。
在上面文献中提到修改HelloWorld代码:
上述代码创建了5个实例p1、p2、p3、p4和p5,它们的类型都是Person继承层次树中的引用类型,p1和p4是Student实例,p2和p5是Worker实例,p3是Person实例。首先,对象类型转换一定发生在继承的前提下,p1和p2都声明为Person类型,而实例是由Person子类型实例化的。
下表归纳了p1、p2、p3、p4和p5这5个实例与Worker、Student和Person这3种类型之间的转换关系。
类型转换表:
作为这段程序的编写者是知道p1本质上是Student实例,但是表面上看是Person类型,编译器也无法推断p1的实例是Person、Student还是Worker。此时可以使用instanceof操作符来判断它是哪一类的实例。
引用类型转换也是通过小括号运算符实现,类型转换有两个方向:将父类引用类型变量转换为子类类型,这种转换称为向下转型(downcast);将子类引用类型变量转换为父类类型,这种转换称为向上转型(upcast)。向下转型需要强制转换,而向上转型是自动的。
下面通过示例详细说明一下向下转型和向上转型,在HelloWorld.java的main方法中添加如下代码:
上述代码第①行将p4对象转换为Person类型,p4本质上是Student实例,这是向上转型,这种转换是自动的,其实不需要小括号(Person)进行强制类型转换。
代码第②行和第③行是向下类型转换,它们的转型都能成功。而代码第④、⑤、⑥行都会发生运行时异常ClassCastException,如果不能确定实例是哪一种类型,可以在转型之前使用instanceof运算符判断一下。
本章在前一篇首先介绍了Java中的继承概念,在继承时会发生方法的覆盖、变量的隐藏。然后介绍了Java中的多态概念,读者需要熟悉多态发生的条件,掌握引用类型检查和类型转换。
看到这点个赞再走吧