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("平时要做的事情");
    }
}


public class Student extends Person {
    String name = "学生";
    @Override
    public void dayTime() {
        System.out.println("学习");
    }
    public void nightTime(){
        System.out.println("做作业");
    }
}


public class Teacher extends Person {
    String name = "老师";
    @Override
    public void dayTime() {
        System.out.println("教书");
    }
}


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


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();
    }
}

4dfb971f953a46018557b2efcc286083.png


3️⃣IDEA提供的解决方法


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


f2554b5e9efc458e81ae8f8910e41b10.png


三、引用类型转换


1️⃣概述


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


2️⃣向上转型


1.概述


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


2.格式


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


3️⃣向下转型

1.概述


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


 
         

2.格式


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


Person p = new Student();
Student s = (Student)p


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();
    }
}


运行结果


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


35bee45797364cf3aaa5f50e42a878e3.png


4️⃣转型异常


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


Person p1 = new Student();
Teacher t = (Teacher)p1;
        t.dayTime();


d3092f470c594b85b54d8663707701f2.png


这里会有报错: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
        }
    }  
}


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("没有这个类型,无法转换");
    }
    }  
}


五、结语


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

相关文章
|
18天前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
19 1
|
1月前
|
JavaScript 前端开发 Java
还不明白面向对象? 本文带你彻底搞懂面向对象的三大特征(2024年11月Java版)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。如果你从我的文章中受益,欢迎关注我,我将持续更新更多优质内容。你的支持是我前进的动力!🎉🎉🎉
24 0
还不明白面向对象? 本文带你彻底搞懂面向对象的三大特征(2024年11月Java版)
|
1月前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
37 2
|
2月前
|
存储 Java 测试技术
Java零基础-多态详解
【10月更文挑战第10天】Java零基础教学篇,手把手实践教学!
35 4
|
2月前
|
Java 编译器 程序员
Java多态背后的秘密:动态绑定如何工作?
本文介绍了Java中多态的实现原理,通过动态绑定和虚拟方法表,使得父类引用可以调用子类的方法,增强了代码的灵活性和可维护性。文中通过具体示例详细解析了多态的工作机制。
73 4
|
3月前
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
2月前
|
Java
java继承和多态详解
java继承和多态详解
52 5
|
2月前
|
存储 Java 测试技术
Java零基础-多态详解
【10月更文挑战第1天】Java零基础教学篇,手把手实践教学!
30 1
|
2月前
|
安全 Java 编译器
【一步一步了解Java系列】:重磅多态
【一步一步了解Java系列】:重磅多态
25 3
|
3月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
36 4