今天我们来看Java面向对象的最后一个特性:多态。继承是多态的基础,要使用多态,就必须要有继承。下面我们来具体看看多态。
说明
为了方便后面的叙述,我们现在这里定义两个类,父类(superClass)、子类A(subclassA)和子类B(subClassB),具体如下:
public class superClass { public void show() { System.out.println("我是父类"); } } //***************************************************************** public class subClassA extends superClass{ //重写父类的方法show() public void show() { System.out.println("我是子类A"); } } //***************************************************************** public class subClassB extends superClass{ public void method() { System.out.println("我是子类B"); } }
多态
多态是同一个行为具有多个不同表现形式或形态的能力,简单说就是对象的多种形态,包括引用多态和方法多态。
1. 引用多态
我们都知道,父类的引用可以指向本类的对象,比如
superClass parents1=new superClass()
,这是显然可以的。既然我们讲多态,那就说明父类的引用还可以指向其他的对象,实际上,父类的引用还可以指向子类的对象,如superClass parents2=new subClassA()
或者superClass parents3=new subClassB()
,这也是可以的。2. 方法多态
上面说到父类的引用可以指向本类和子类的对象,那么就要相应的创建本类对象和子类对象,对象可以用来调用方法,于是就有了对应的方法多态。在创建本类对象时,调用的方法为本类方法,创建子类对象时,调用的方法为子类重写的方法或者继承的方法。如下所示:
parents1.show(); //本类对象调用本类方法 parents2.show(); //子类对象调用子类重写的方法 parents3.show(); //子类对象调用子类继承的方法
引用类型转换
引用类型转换是父类类型与子类类型之间的转换,分为向上类型转换和向下类型转换。
1. 向上类型转换
向上类型转换就是说把子类的引用类型转换成父类的引用类型,比如创建了一个子类对象
subClassA subObj=new subClassA()
,之后又执行superClass superObj=subObj
,这就相当于通过superObj把subObj的类型提升为superClass,这就是向上类型转换,也称为自>动类型转换,它是没有风险的。2. 向下类型转换
与之相反的是向下类型转换,即把父类的引用类型转换为子类的类型,把大化小,是一种强制类型转换。比如对于对象
superClass superObj= new superClass()
,之后又执行语句subClassA subObj=(subClassA)superObj
,这种转换是存在风险的,在编译器中编译不会报错,但是在运行过程中可能会发生异常。比如下面的代码段:subClassA subObj1=new subClassA(); //创建子类对象subObj1 superClass superObj=subObj1; //向上类型转换 subClassB subObj2=(subClassB)superObj; //向下类型转换
上述代码在语法上没有错误,编译也可以通过。但是,仔细观察会发现,最后一句代码表面上虽然是向下类型转换,但是superObj本质上指向的是子类A的对象subobj1,上面的代码结果实际上相当于是把子类A的引用类型转换为子类B的类型,这是不允许的,两个子类间是无法进行类型转换的,在运行过程中会发生异常,这个风险可以用instanceof运算来规避风险。
3. instanceof运算
上面说到在向下类型转换时可能会发生异常,可以同instanceof运算来规避,instanceof是一个二元运算,类似于“==”,返回一个布尔值,用法为
boolean result=object instanceof Class
。我们可以在向下类型转换时添加一个判断语句,具体如下:subClassA subObj1=new subClassA(); //创建子类对象subObj1 superClass superObj=subObj1; //向上类型转换 if(superObj instanceof subClassB){ subClassB subObj2=(subClassB)superObj; //向下类型转换 }else{ System.out.println("错误类型转换"); }
这样就可以避免程序在运行时发生异常而中断了。