【Java寒假打卡】Java基础-多态

本文介绍了Java中的多态性,包括其前提条件(继承、方法重写)、成员访问特点、好处(如提高代码扩展性)和弊端(无法直接调用子类特有方法)。文章还讨论了向上和向下转型,以及转型可能带来的ClassCastException风险及解决方案(使用instanceof关键字进行类型检查)。
摘要由CSDN通过智能技术生成

概述

同一个对象在不同时刻表现出来的不同形态

在这里插入图片描述

多态的前提和体现

  • 有继承/实现关系
  • 有方法重写。子类对父类进行方法重写
  • 有父类引用指向子类对象
package com.hfut.edu.test1;

public class Test1 {
    public static void main(String[] args) {
        // 多态三个条件
        // 继承/实现关系
//        有方法重写
        // 父类引用指向子类对象

        Animal a = new Cat();
        a.eat();// 调用子类重写之后的方法


    }
}


class Animal{
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

多态中成员访问的特点

  • 构造方法:和继承一样,子类会通过super关键字访问父类构造方法
  • 成员变量:编译看左边(父类),执行看左边(父类)
  • 成员方法:编译看左边 父类,执行看右边 子类
package com.hfut.edu.test1;

public class Test1 {
    public static void main(String[] args) {
        // 多态三个条件
        // 继承/实现关系
        // 有方法重写
        // 父类引用指向子类对象

        Animal a = new Cat();
        a.eat();// 调用子类重写之后的方法
        System.out.println(a.num);// 调用父类的成员变量
    }
}

class Animal{
    int num  = 10;
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Cat extends Animal{

    int  num = 20;
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

为什么成员变量和成员方法的访问不一样?

  • 因为成员方法有重写,但是成员变量没有重写

多态的好处和弊端

  • 好处:父类引用可以指向不同的子类对象,调用子类重写的父类方法
package com.hfut.edu.test1;

public class Test2 {
    public static void main(String[] args) {
        useAnimal(new Dog());
        useAnimal(new Cat());
    }

    // 多态调用不同子类对象的方法  因为 父类引用可以接受任意的子类对象
    public static void useAnimal(Animal a){
        a.eat();// 子类对象调用方法  必须是子类重写的方法  父类引用才可以进行调用
//        a.watchHome();// 报错  多态的父类引用 在编译期间会查看该方法是否是子类重写的方法
    }
}

abstract class Animal{
    public abstract void eat();

}

class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃肉");
    }

    public void watchHome(){
        System.out.println("看家");
    }
}

class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

多态的好处和弊端:

  • 多态的好处:提高了程序的扩展性
    具体体现:定义方法的时候,使用父类引用作为参数,该方法就可以接受这个父类的任意子类对象

  • 多态的弊端:不能使用子类的特有功能,也就是子类自己的特有的方法,父类引用不可以直接调用

多态中转型

  • 向上转型:父类引用指向子类对象
  • 向下转型:父类引用转为子类对象
package com.hfut.edu.test1;

public class Test2 {
    public static void main(String[] args) {

        Animal a = new Cat();// 向上转型 父类引用指向子类对象
        a.eat();// 弊端 只能调用父类与子类共有的方法

        // 向下转型:从父类类型 转换回子类类型
        Cat c = (Cat)a;// 需要强制类型转换
        c.method();// 转换之后 调用子类对象特有的方法
    }

    // 多态调用不同子类对象的方法  因为 父类引用可以接受任意的子类对象
    public static void useAnimal(Animal a){
        a.eat();// 子类对象调用方法  必须是子类重写的方法  父类引用才可以进行调用
//        a.watchHome();// 报错  多态的父类引用 在编译期间会查看该方法是否是子类重写的方法
    }
}

abstract class Animal{
    public abstract void eat();

}

class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃肉");
    }

    public void watchHome(){
        System.out.println("看家");
    }
}

class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }

    public void method()
    {
        System.out.println("猫抓老鼠");
    }
}

多态中转型存在的风险

  • 概述:如果被转换的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
package com.hfut.edu.test1;

public class Test2 {
    public static void main(String[] args) {
        useAnimal(new Dog());
        useAnimal(new Cat());// 报错 强制类型转换出现错误  类型不匹配

    }

    // 多态调用不同子类对象的方法  因为 父类引用可以接受任意的子类对象
    public static void useAnimal(Animal a){
        a.eat();// 子类对象调用方法  必须是子类重写的方法  父类引用才可以进行调用
//        a.watchHome();// 报错  多态的父类引用 在编译期间会查看该方法是否是子类重写的方法

        Dog d = (Dog)a;// 强制类型转换
        d.watchHome();// 调用子类对象特有的方法

    }
}

abstract class Animal{
    public abstract void eat();

}

class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃肉");
    }

    public void watchHome(){
        System.out.println("看家");
    }
}

class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }

    public void method()
    {
        System.out.println("猫抓老鼠");
    }
}


解决办法:使用关键字instanceof

使用格式:变量名 instanceof 类型

通俗的解释:判断关键字左边的变量 是否是右边的类型 返回boolean类型结果

package com.hfut.edu.test1;

public class Test2 {
    public static void main(String[] args) {
        useAnimal(new Dog());
        useAnimal(new Cat());// 报错 强制类型转换出现错误  类型不匹配

    }

    // 多态调用不同子类对象的方法  因为 父类引用可以接受任意的子类对象
    public static void useAnimal(Animal a){
        a.eat();// 子类对象调用方法  必须是子类重写的方法  父类引用才可以进行调用
//        a.watchHome();// 报错  多态的父类引用 在编译期间会查看该方法是否是子类重写的方法

        if(a instanceof Dog){
            Dog d = (Dog)a;// 强制类型转换
            d.watchHome();// 调用子类对象特有的方法
        }


    }
}

abstract class Animal{
    public abstract void eat();

}

class Dog extends Animal{
    public void eat(){
        System.out.println("狗吃肉");
    }

    public void watchHome(){
        System.out.println("看家");
    }
}

class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }

    public void method()
    {
        System.out.println("猫抓老鼠");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少写代码少看论文多多睡觉

求打赏,求关注,求点赞

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值