一、什么是多态
事物的多种展现形式。
二、多态的好处
提高程序中代码的复用性、扩展性
三、多态的前提
- 有继承关系、实现关系
- 子类重写父类/父接口中的方法
四、多态的书写格式
父类/父接口 父引用 = new 子类(); // 父引用指向子类对象 JavaStudent javaStu = new JavaStudent(); // 使用事物的本身类型来定义 Student javaStu = new JavaStudent(); // 使用事务的父类型来定义
五、静态多态
- 也称为编译期多态
- 概念就是同一个对象的不同行为体现
- 代码体现为方法的重载
举例
同一个对象进行登录,可以有不同的登录方式,(用户名/密码、手机验证码、人脸识别);
举例代码如下
// Student.java public class JavaStudent extends Student{ @Override public boolean login(String name, String pwd) { if(name.equals("张三") && pwd.equals("123456")){ return true; }else{ return false; } } @Override public boolean login(int phoneCode) { if(phoneCode == 1234){ return true; }else{ return false; } } @Override public boolean login(String face) { if(face.equals("张三的人脸信息")){ return true; }else{ return false; } } } // ExamSys.java public class ExamSys { public static void main(String[] args) { init(); } public static void init(){ System.out.println("*******************黑马考试系统***********************"); System.out.println("请选择学科 1、Java 2、UI"); int num = new Scanner(System.in).nextInt(); switch(num){ case 1: JavaStudent javaStu = new JavaStudent(); if(selectLogin(javaStu)){ System.out.println("登录成功"); } break; case 2: UIStudent uiStu = new UIStudent(); if(selectLogin(uiStu)){ System.out.println("登录成功"); } break; default: System.out.println("选择错误,退出系统"); System.exit(0); break; } } public static boolean selectLogin(Student stu){ System.out.println("*************************************************"); System.out.println("请选择登录方式:"); System.out.println("1、用户名密码登录"); System.out.println("2、手机验证码登录"); System.out.println("3、人脸识别登录"); System.out.println("*************************************************"); int num = new Scanner(System.in).nextInt(); boolean result = false; switch(num){ case 1: result = stu.login("用户名", "密码"); break; case 2: result = stu.login(123); break; case 3: result = stu.login("人脸信息"); break; } return result; } }
上述学生类登录功能分别有三种:用户名密码登录、手机验证码登录、人脸识别登录,就是静态多态。
六、动态多态
- 也称为运行期多态
- 不同对象的相同行为体现
- 代码的体现为方法的重写
- 有继承关系、实现关系
- 子类重写父类/父接口中的方法
举例
不同对象进行考试,对象都有考试功能(Java学生 =》考试 UI学生=》考试);
举例代码如下
// ExamSys.java public class ExamSys { public static void main(String[] args) { init(); } public static void init(){ System.out.println("*******************黑马考试系统***********************"); System.out.println("请选择学科 1、Java 2、UI"); int num = new Scanner(System.in).nextInt(); switch(num){ case 1: JavaStudent javaStu = new JavaStudent(); if(selectLogin(javaStu)){ System.out.println("登录成功"); } break; case 2: UIStudent uiStu = new UIStudent(); if(selectLogin(uiStu)){ System.out.println("登录成功"); } break; default: System.out.println("选择错误,退出系统"); System.exit(0); break; } } public static boolean selectLogin(Student stu){ System.out.println("*************************************************"); System.out.println("请选择登录方式:"); System.out.println("1、用户名密码登录"); System.out.println("2、手机验证码登录"); System.out.println("3、人脸识别登录"); System.out.println("*************************************************"); int num = new Scanner(System.in).nextInt(); boolean result = false; switch(num){ case 1: result = stu.login("用户名", "密码"); break; case 2: result = stu.login(123); break; case 3: result = stu.login("人脸信息"); break; } return result; } }
上述代码 selectLogin 方法接收参数类型为Student类型,然后调用的时候传的是 JavaStudent javaStu = new JavaStudent()和UIStudent uiStu = new UIStudent()都可以成功。
动态多态在开发中的应用场景有如下2种
- 方法中参数多态
- 方法返回值多态
上述代码就是方法中参数多态,下面代码就是返回值多态
public Student createStudnet(int flag, String name, int age){ if(flag == 1){ return new JavaStudent(name, age); }else{ return new UIStudent(name, age); } }
七、多态中方法的执行特点
- 成员变量不参与多态 ,只有成员方法才有多态现象
- 多态的格式调用方法,指的是父类/父接口型调用方法,就是多所调用的方法必须在父类型/父接口中有存在,执行的时候,会执行子类重写的方法,如果子类没有重写方法,会向父类/接口找到方法执行
- 使用多态调用方法,不能调用子类特有的方法(多态的弊端)
八、多态的类型转换
有2种,就是向上转型和向下转型。
8.1、向上转型
在书写多态代码时,就已经实现向上转型
Student stu = new JavaStudent(); // JavaStudent类型转换为Student类型(类型提升)
注意,stu引用的是子类对象,虽然类型向上转型了,但底层实际还是子类。
8.2、向下转型
向下转型首先要了解动态多态的弊端,就是上面说的父引用无法调用子类特有的方法,这里使用多态的向下转型就可以解决这个问题。
向下转型的书写格式如下
子类 子类对象 = (子类) 父引用;
// 多态体现:向上转型 Student stu = new JavaStudent(); stu.project(""); // 父类对象无法调用子类特有方法 // 访问JavaStuent类中的特有方法 JavaStudent javaStu = (JavaStudent) stu; // 向下转型,把父类型转换为子类类型 javaStu.project("考试系统");
九、instanceof
使用instanceof关键字可以避免ClassCastException异常
书写格式
if(对象名 instanceof 数据类型){ // instanceof关键字的作用:判断指定的对象是否为某种类型 // 如果是返回true,不是返回false }
举例代码如下
// 开始考试 public static void startExam(Student stu){ String str = ""; if(stu instanceof JavaStudent){ // 检查stu对象底层是否为JavaStudent类型 str = "Java"; }else if(stu instanceof UIStudent){ str = "UI"; } System.out.println("************************" + str + "考试题**************************"); stu.exam(); }