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


五、结语


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

相关文章
|
8月前
|
Java
Java基础语法与面向对象
重载(Overload)指同一类中方法名相同、参数列表不同,与返回值无关;重写(Override)指子类重新实现父类方法,方法名和参数列表必须相同,返回类型兼容。重载发生在同类,重写发生在继承关系中。
216 1
|
8月前
|
存储 Java 关系型数据库
Java 项目实战基于面向对象思想的汽车租赁系统开发实例 汽车租赁系统 Java 面向对象项目实战
本文介绍基于Java面向对象编程的汽车租赁系统技术方案与应用实例,涵盖系统功能需求分析、类设计、数据库设计及具体代码实现,帮助开发者掌握Java在实际项目中的应用。
315 0
|
9月前
|
安全 Java 编译器
Java面向对象
本文深入讲解了Java面向对象编程(OOP)的四大特性:封装、继承、多态与抽象,以及方法的设计与使用。通过示例展示了如何用类和对象组织代码,提升程序的可维护性与扩展性。
|
10月前
|
存储 Java 测试技术
Java基础 - 面向对象
面向对象编程是Java的核心,包含封装、继承、多态三大特性。封装隐藏实现细节,提升代码可维护性与安全性;继承实现类间IS-A关系,支持代码复用;多态通过继承、重写与向上转型,实现运行时方法动态绑定,提升系统扩展性与灵活性。
160 0
|
12月前
|
人工智能 Java 编译器
Java:面向对象
本文介绍了Java编程中的核心概念,包括包的命名规范与自动导入机制、构造方法的特点与使用、`this`和`super`关键字的作用、继承的基本规则、访问权限的设置、封装的意义、多态的实现原理以及`static`关键字的用法。通过详细解析每个知识点,并结合代码示例,帮助读者深入理解Java面向对象编程的核心思想与实践技巧。内容适合初学者及进阶开发者学习参考。
248 0
|
Java 编译器 程序员
java中重载和多态的区别
本文详细解析了面向对象编程中多态与重载的概念及其关系。多态是OOP的核心,分为编译时多态(静态多态)和运行时多态(动态多态)。编译时多态主要通过方法重载和运算符重载实现,如Java中的同名方法因参数不同而区分;运行时多态则依赖继承和方法重写,通过父类引用调用子类方法实现。重载是多态的一种形式,专注于方法签名的多样性,提升代码可读性。两者结合增强了程序灵活性与扩展性,帮助开发者更好地实现代码复用。
726 0
|
缓存 安全 Java
java面试-基础语法与面向对象
本文介绍了 Java 编程中的几个核心概念。首先,详细区分了方法重载与重写的定义、发生阶段及规则;其次,分析了 `==` 与 `equals` 的区别,强调了基本类型和引用类型的比较方式;接着,对比了 `String`、`StringBuilder` 和 `StringBuffer` 的特性,包括线程安全性和性能差异;最后,讲解了 Java 异常机制,包括自定义异常的实现以及常见非检查异常的类型。这些内容对理解 Java 面向对象编程和实际开发问题解决具有重要意义。
|
Java
Java 面向对象编程的三大法宝:封装、继承与多态
本文介绍了Java面向对象编程中的三大核心概念:封装、继承和多态。
749 15
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
175 1
|
JavaScript 前端开发 Java
还不明白面向对象? 本文带你彻底搞懂面向对象的三大特征(2024年11月Java版)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。如果你从我的文章中受益,欢迎关注我,我将持续更新更多优质内容。你的支持是我前进的动力!🎉🎉🎉
237 0
还不明白面向对象? 本文带你彻底搞懂面向对象的三大特征(2024年11月Java版)