多态性
1,多态性简介
多态是面向对象中的三大主要特征,多态性是在继承性的基础上扩展出来的,可以实现父子类之间转换处理。
·多态性的概念
在Java之中对于多态性有两种实现的模式:
·方法的多态性:
|-①方法的重载:同一个方法名称可以根据传入的参数的类型或个数的不同实现不同功能的执行;
1 public voidprint(){2 System.out.println("无参重载方法");3 }4 public voidprint(String str){5 System.out.println(str);6 }
|-②方法的覆写:同一个方法可以根据使用的子类的不同有不同的实现;
1 classDatabaseMessage{2 public voidprint(){3 System.out.println("Oracle数据库连接信息....");4 }5 }6 classNetworkMessage{7 public voidprint(){8 System.out.println("网络连接信息....");9 }10 }
|-③对象的多态性:父子实例之间的转换处理,它有两种模式:
·对象向上转型:父类 父类实例 =子类实例、自动完成转换;
·对象向下转型:子类 子类实例 = (子类)父类实例、强制完成转换;
从实际的转型处理来讲,大部分情况下考虑最多的一定是对象的向上转型(90%)、对于对象的向下转型往往都在使用子类的特殊功能(子类可以对父类进行功能扩充)的时候(3%)。
2,对象向上转型(接收或返回参数的统一性)
对象转型的处理属于多态性,而这一特性必须在继承性的基础上实现。
·范例:简单代码
1 classMessage{2 public voidprint(){3 System.out.println("无参重载方法");4 }5 public voidprint(String str){6 System.out.println(str);7 }8 }9 class DatabaseMessage extendsMessage{10 public voidprint(){11 System.out.println("Oracle数据库连接信息....");12 }13 }14 public classMain {15 public static voidmain(String[] args) {16 DatabaseMessage msg=new DatabaseMessage();//①方法的覆写
17 msg.print();18 System.out.println("Hello World!");19 }20 }
·范例:观察向上转型本程序是一个最简单的方法覆写操作实现,整体的程序之中可以发现,由于现在实例化的是子类对象,并且子类对象覆写了父类中的print()方法,所以调用的是被覆写过的方法。
1 Message msg=new DatabaseMessage();//向上转型
·范例:向上转型的优势那么这个时候就需要进行思考了,向上转型这种操作有什么主要的用处呢?
1 classMessage{2 public voidprint(){3 System.out.println("无参重载方法");4 }5 public voidprint(String str){6 System.out.println(str);7 }8 }9 class DatabaseMessage extendsMessage{10 public voidprint(){11 System.out.println("Oracle数据库连接信息....");12 }13 }14 class WebServerMessage extendsMessage{15 public voidprint(){16 System.out.println("WEB服务器连接信息....");17 }18 }19 public classMain {20 public static voidmain(String[] args) {21 fun(new DatabaseMessage());//Message msg=new DatabaseMessage()
22 fun(new WebServerMessage());//Message msg=new WebServerMessage()
23 }24 public static void fun(Message msg){//不管现在传递的是哪一个子类都可以接收
25 msg.print();26 }27 }
·范例:方法重载向上转型的主要特点在于,可以对参数进行统一的设计。但是为什么此时不使用重载来解决当前问题呢?
1 public static void fun(DatabaseMessage msg){//不管现在传递的是哪一个子类都可以接收
2 msg.print();3 }4 public static void fun(WebServerMessage msg){//不管现在传递的是哪一个子类都可以接收
5 msg.print();6 }
现在的操作利用了重载解决了当前的设计,的确可以实现与之前完全一样的效果。但是在进行程序类设计时候,除了满足当前的要求之外,还需要做出可维护设计,如果说现在随着项目的发展,Message产生3万个子类,那么这个时候每当扩充一个Message子类之后就需要追加一个fun()的方法重载,这样就对我们程序的维护性造成了很大的困难。
3,对象向下转型
向下转型的主要特点在于需要使用到一些子类自己特殊的定义处理。
·范例:向下转型(需要强制转换)
1 classPerson{2 public voidprint(){3 System.out.println("一个普通人");4 }5 }6 class SuperMan extendsPerson{7 public voidfly(){8 System.out.println("I can fly");9 }10 public voidfire(){11 System.out.println("I can make fire out");12 }13 }14 public classMain {15 public static voidmain(String[] args) {16 Person person=new SuperMan();//向上转型
17 person.print();18 SuperMan superMan=(SuperMan) person;//向下转型,强制转换
19 superMan.fly();20 }21 }
·范例:观察错误的程序向上描述的是一些公共的特征,而向下描述的是子类自己特殊的定义环境。但是我们需要明确的是,向下转型并不是一件安全的事情。因为在进行向下转型之前一定要发生向上转型。
1 public classMain {2 public static voidmain(String[] args) {3 Person person=new Person();//没有转型
4 person.print();5 SuperMan man=(SuperMan) person;//SuperMan类与Person类
6 }7 }
1 Exception in thread "main" java.lang.ClassCastException: class Person cannot be cast to class SuperMan (Person and SuperMan are in unnamed module of loader 'app')
以后只有是发生对象的向下转型之前一定要先发生向上转型,两个没有任何关系的实例如果要发生强制转换,那么就会出现【ClassCastException】异常,所以向下转型并不是一件安全的事情。
·通俗的话儿来讲讲:
野猪与家猪都是猪(父类),它们都可以向上转型成猪类。但是如果有一头猪,那么它的品种你不能确定是(野猪or家猪)——不能向下转型。但是在已知一头野猪向上转型成为猪,那么我们可以确定它也一定是野猪(向下转型)。
4,instanceo关键字
通过分析可以发现向下转型本身是一件存在有安全隐患的操作,所以为了保证向下转型的正确性,往往需要在进行转型之前进行判断,判断某个实例是否是某个类的对象,这个就需要通过instanceof实现。
该判断将返回一个boolean类型,如果true表示实例是指定类对象。
·范例:观察instanceof的使用
1 public classMain {2 public static voidmain(String[] args) {3 Person person=new Person();//不转型
4 System.out.println(person instanceof Person);//true
5 System.out.println(person instanceof SuperMan);//false
6 }7 }
·范例:观察instanceof关键字
1 public classMain {2 public static voidmain(String[] args) {3 Person person=new SuperMan();//向上转型
4 System.out.println(person instanceof Person);//true
5 System.out.println(person instanceof SuperMan);//true
6 }7 }
1 public classMain {2 public static voidmain(String[] args) {3 Person person=new SuperMan();//向上转型
4 if(person instanceofSuperMan){5 SuperMan man=(SuperMan) person;6 man.print();7 }8 }9 }
在以后进行一些完善性的程序开发的过程之中,对于转型之前一定要使用instanceof先进行判断。所以在日后进行项目的开发过程之中,如果要执行对象的向下转型,最好先判断一次。
【ClassCastException】异常就是向下转型出错的异常。