• Java面向对象进阶4——多态的弊端及解决方法


    一、前言

    本文将针对面向对象三大特征中的多态的弊端及其解决方法展开讲述

    二、概述

    1️⃣弊端产生原因

    因为多态编译阶段是看左边父类类型的,所以当子类有些独有的功能,此时多态的写法就无法访问子类独有功能了

    2️⃣弊端演示

    public class Person {
    
        String name = "人";
    
        public void sleep(){
            System.out.println("睡觉");
        }
    
        public void eat(){
            System.out.println("吃饭");
        }
    
        public void drink(){
            System.out.println("喝水");
        }
    
        public void dayTime(){
            System.out.println("平时要做的事情");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    public class Student extends Person {
    
        String name = "学生";
        @Override
        public void dayTime() {
            System.out.println("学习");
        }
        public void nightTime(){
            System.out.println("做作业");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    public class Teacher extends Person {
    
        String name = "老师";
        @Override
        public void dayTime() {
            System.out.println("教书");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    当我们测试这个代码的时候会报错

    public class Test {
        public static void main(String[] args) {
            System.out.println("-----学生的行为-----");
            Person p1 = new Student();
            p1.drink();
            p1.eat();
            p1.sleep();
            p1.dayTime();
            p1.nightTime();
    
            System.out.println("-----老师的行为-----");
            Person p2 = new Teacher();
            p2.drink();
            p2.eat();
            p2.sleep();
            p2.dayTime();
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    3️⃣IDEA提供的解决方法

    当我们选中爆红处再使用 Alt + Enter IDEA会提示我们解决方案,但是这依然没办法使用子类中特有的方法
    在这里插入图片描述

    三、引用类型转换

    1️⃣概述

    当出现这种编译错误时,我们就需要对其进行转型,而多态的转型又分为向上转型和向下转型

    2️⃣向上转型

    1.概述

    多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。

    2.格式

    父类类型 变量名 = new 子类类型();

    Person p = new Student();

    3️⃣向下转型

    1.概述

    父类类型向子类类型向下转换的过程,这个过程是强制的。一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型

    2.格式

    子类类型 变量名 = (子类类型) 父类变量名

    Person p = new Student();
    Student s = (Student)p
    
    • 1
    • 2

    3.具体代码

    public class Test {
        public static void main(String[] args) {
            System.out.println("-----学生的行为-----");
            Person p1 = new Student();
            p1.drink();
            p1.eat();
            p1.sleep();
            p1.dayTime();
            ((Student) p1).nightTime();
    
            System.out.println("-----老师的行为-----");
            Person p2 = new Teacher();
            p2.drink();
            p2.eat();
            p2.sleep();
            p2.dayTime();
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    运行结果

    -----学生的行为-----
    喝水
    吃饭
    睡觉
    学习
    做作业
    -----老师的行为-----
    喝水
    吃饭
    睡觉
    教书

    在这里插入图片描述

    4️⃣转型异常

    用上面的程序做例子,当我们写如下代码时编译不会出错,但是运行会出错

    Person p1 = new Student();
    Teacher t = (Teacher)p1;
            t.dayTime();
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    这里会有报错:ClassCastException——类型转换异常,所以在转换的时候一定要看清楚两个是否是子父类关系,如果不是则不能转换

    四、instanceof关键字

    1️⃣概述

    为了避免上文提到的类型转换异常,我们可以用这个关键字来判断是否可以转型 如果变量属于该数据类型或者其子类类型,返回true
    如果变量不属于该数据类型或者其子类类型,返回false

    2️⃣具体使用

    
    public class Test {
        public static void main(String[] args) {
            // 向上转型  
            Person p1 = new Student();  
            p1.eat();               // 调用的是 Student 的 eat
    
            // 向下转型  
            if (a instanceof Student){
                Student s = (Student)p1;       
                s.nightTime();        // 调用的是 Student 的 nightTime
            } 
            else if (p1 instanceof Teacher){
                Teacher t = (Teacher)p1;       
                t.nightTime();      // 调用的是 Dog 的 nightTime
            }
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3️⃣JDK14新特性

    
    public class Test {
        public static void main(String[] args) {
            // 向上转型  
            Person p1 = new Student();  
            p1.eat();               // 调用的是 Student 的 eat
    
            // 向下转型  
            if (a instanceof Student s){   
                s.nightTime();        // 调用的是 Student 的 nightTime
            } 
            else if (p1 instanceof Teacher t){      
                t.nightTime();      // 调用的是 Dog 的 nightTime
            }
            else{
        		System.out.println("没有这个类型,无法转换");
    		}
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    五、结语

    本文针对多态的一些弊端讲述了其解决方法,有利于更加高效正确的编写程序

  • 相关阅读:
    leetcode - 二分查找
    【墨染】找特有姿态!基于【灵茶山艾府】题解的补充图解
    area.js 文件下载
    SIPp使用经验
    百度 | 文心一言也开始收费了
    redis未授权访问
    异常检测主要方法总结
    博客程序系统其它功能扩充
    Java调用tess4j完成 OCR 文字识别
    自己做的游戏,为什么报错啊?求解
  • 原文地址:https://blog.csdn.net/Alita233_/article/details/126408822