Java——多态

目录

一:认识

[1. 概念](#1. 概念)

[2. 格式](#2. 格式)

[3. 案例演示](#3. 案例演示)

二:访问特点

[1. 成员变量的访问](#1. 成员变量的访问)

[2. 成员方法的访问](#2. 成员方法的访问)

[3. 对比(总结)](#3. 对比(总结))

三:向上转型

四:向下转型

[1. 类转换异常](#1. 类转换异常)

[2. Instanceof](#2. Instanceof)

五:多态的好处

六:总结


一:认识

1. 概念

面向对象的三大特征:封装,继承,多态。多态的前提是 extends 继承implements 实现;

多态性指一个对象的多种形态。是对于对象而言的,与类无关;

2. 格式

继承:父类名称 对象名= new 子类名称( );

实现:接口名称 对象名 = new 实现类名称( );

【即 左父右子

3. 案例演示

定义一个 Animal类,然后定义一个 Cat类,最后定义一个测试类:

复制代码
 我们定义一个AnimalClass类,CatClass类,还有一个测试类,通过向上转型来访问父类的 eat方法。
java 复制代码
public class AnimalClass {
    String name;//姓名
    int age;//年龄
    public void eat(){//普通方法
        System.out.println("吃饭饭");
    }
}
java 复制代码
public class CatClass extends AnimalClass{
    public void sleep(){
        System.out.println("爱睡觉");
    }
}
java 复制代码
public class Demo {
    public static void main(String[] args) {
        //左侧父类引用指向右侧子类对象
        AnimalClass a=new CatClass();
        a.eat();
    }
}
java 复制代码
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=2815:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.Demo
吃饭饭

进程已结束,退出代码0

二:访问特点

1. 成员变量的访问

直接访问:直接通过对象名称访问成员变量,等号左边是谁, 就优先用谁,没有往上找;

间接访问:通过成员方法间接访问成员变量,**成员方法属于谁,**就优先用谁,没有往上找;

案例演示:

我们定义一个父类:AnimalClass , 定义一个子类:CatClass , 再定义一个测试类:Demo ;

测试类中对成员变量分别直接/间接访问;

另外,父类子类中的成员方法重名,子类优先调用自己的成员方法,若没有,再往上找,调用父类的;

java 复制代码
package Multi01;
public class AnimalClass {
    int age=66;//年龄
    public void show(){//普通方法
        System.out.println(age);
    }
}
java 复制代码
package Multi01;
public class CatClass extends AnimalClass{
    int age=100;
    public void show(){
        System.out.println(age);
    }
}
java 复制代码
package Multi01;
public class Demo {
    public static void main(String[] args) {
        //左侧父类引用指向右侧子类对象
        AnimalClass a=new CatClass();
        System.out.println(a.age);//直接访问成员变量
        System.out.println("=========");
        a.show();//间接通过方法访问成员变量
    }
}
java 复制代码
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=2334:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.Demo
66
=========
100

进程已结束,退出代码0

2. 成员方法的访问

看 new 的是谁,就优先用谁里面的方法,没有,往上找;

即对于成员方法来说:编译看左边,运行看右边;(没有往上找)

编译是指源文件转换为字节码文件的过程,运行是指执行字节码文件的过程;

我们定义一个父类:Man,定义一个子类:Child, 再定义一个测试类DemoMan.

java 复制代码
public class Man {
    String name;        //成员变量
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void play(){ //成员方法
        System.out.println("这是父类的方法!");
    }
}
java 复制代码
package Multi01;
public class Child extends Man{
    String name="刘备备";
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void sleep(){
        System.out.println("这是子类的方法");
    }
}
java 复制代码
package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();//多态
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//子类中的show方法
        m.play();//往上找到父类的成员方法
    }
}
java 复制代码
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=2780:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.DemoMan
刘备备
这是父类的方法!

进程已结束,退出代码0

3. 对比(总结)

成员变量:编译看左边,执行看左边;

成员方法:编译看左边,运行看右边:

(图片为转载,非本人绘制)

三:向上转型

含义:把右侧的 "new 子类名( )"当作父类来使用;

格式:父类名 对象名 = **new 子类名( ),**就是多态的格式。

向上转型一定是安全的,是从小范围到大范围。类似于数据类型的自动类型转换;

其实咱们前面提到的多态都是向上转型的,这里就不提供代码进行举例;

四:向下转型

含义:将父类对象还原成为本来的子类对象;

格式:子类名 子类对象 = (子类名)父类对象

我们定义一个父类 Man,一个子类 Child ,一个测试类DemoMan,将猫向上转型扩大范围当作动物来访问动物中的show,play方法;为了访问猫本身特有的方法,我们将其向下转型还原为本身来访问pure方法;

java 复制代码
public class Man {
    String name;        //成员变量
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void play(){ //成员方法
        System.out.println("这是父类的方法!");
    }
}
java 复制代码
package Multi01;
public class Child extends Man{
    String name="刘备备";
    public void show(){ //成员方法
        System.out.println(name);
    }
    public void pure(){
        System.out.println("小孩子天真又可爱");
    }
}
java 复制代码
package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();  //向上转型,孩子扩大范围为man
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//编译左边成功,执行右边子类中的show方法
        m.play();//编译左边成功,执行右边子类中的pay,没有往上找

        Child c=(Child) m;//向下转型,还原为Child本身
        c.pure();//调用本类特有的方法
    }
}

1. 类转换异常

但是,如果对象创建的时候不是猫,非要向下转型为猫,那么编译器不会报错,但会显示异常( 类转换异常:java.lang.ClassCastException );

java 复制代码
package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();  //向上转型,孩子扩大范围为man
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//编译左边成功,执行右边子类中的show方法
        m.play();//编译左边成功,执行右边子类中的pay,没有往上找
        Child c=(Child) m;//向下转型,还原为Child本身
        c.pure();//调用本类特有的方法
        System.out.println("========");

        Dog d=(Dog) m;//编译不会报错,但会出现异常
    }
}
java 复制代码
C:\Java\jdk-17.0.11\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\lib\idea_rt.jar=4577:C:\Program Files\JetBrains\IntelliJ IDEA 2022.1.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Test\classDemo\out\production\classDemo Multi01.DemoMan
刘备备
这是父类的方法!
小孩子天真又可爱
========
Exception in thread "main" java.lang.ClassCastException: class Multi01.Child cannot be cast to class Multi01.Dog (Multi01.Child and Multi01.Dog are in unnamed module of loader 'app')
	at Multi01.DemoMan.main(DemoMan.java:12)

进程已结束,退出代码1

2. Instanceof

那么,我们怎么确定一个父类引用的对象,原本是哪一个类呢?

在向下转型的时候,我们可以使用 Instanceof 借助 if...else... 语句先判断父类引用的对象原来是哪个类的,再进行下面的操作;

格式 :if ( 父类对象 instangceof子类名 ) {

向下转型;

方法体;

}

java 复制代码
package Multi01;
public class DemoMan {
    public static void main(String[] args) {
        Man m=new Child();  //向上转型,孩子扩大范围为man
        //成员方法的调用:编译看左边,执行看右边,没有往上找
        m.show();//编译左边成功,执行右边子类中的show方法
        m.play();//编译左边成功,执行右边子类中的pay,没有往上找

        if(m instanceof Child){
        Child c=(Child) m;//向下转型,还原为Child本身
        c.pure();//调用本类特有的方法
        System.out.println("========");
        }

        if(m instanceof Dog){
        Dog d=(Dog) m;//编译不会报错,但会出现异常
        }
    }
}

五:多态的好处

多态的好处就是向上转型时,等号左边都是 " 父类名 对象名 " ,对象名的类型都是父

类,不需要根据子类对象来 " 类名 对象名 = new 类名 " 创建,使用时更加灵活;

(图片为转载,非本人绘制)

六:总结

在我看来,向上转型就是把一个子类进行放大成父类使用,向下转型就是把一个类还原

为它本身进行使用。比如,父类为 Animal,子类为 Dog,向上转型就是把 Dog 当作

Amimal 使用 ,向下转型就是把 Dog 还原为 Dog ,以便访问其特有的方法;

相关推荐
Theodore_10223 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸4 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象4 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了5 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
----云烟----5 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024065 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
小二·5 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic5 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it5 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
懒洋洋大魔王5 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq