【Java基础篇】第十三章 方法的覆盖和多态

有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

导读:本篇文章讲解 【Java基础篇】第十三章 方法的覆盖和多态,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

⭐⭐⭐Java基础篇目录⭐⭐⭐


🍁 第一章 Java开发环境搭建
🍁 第二章 标识符与关键字
🍁 第三章 变量
🍁 第四章 数据类型
🍁 第五章 运算符
🍁 第六章 控制语句
🍁 第七章 方法
🍁 第八章 认识面向对象
🍁 第九章 对象的创建和使用
🍁 第十章 封装
🍁 第十一章 this和static
🍁 第十二章 继承
🍁 第十三章 方法的覆盖和多态
🍁 第十四章 super

在这里插入图片描述

1、 方法的覆盖(Override)

子类继承父类后,当继承过来的方法无法满足当前子类的业务需求时,子类有权利对这个方法进行重新编写,有必要进行“方法的覆盖”

😉
方法的覆盖又称方法的重写。


注意区分方法的重载:

方法的重载是一个类中。方法的功能相似的话,建议将方法名定义成一样的。

重载的构成条件是:

  • 在同一个类中
  • 方法名相同
  • 参数列表不同(参数个数、参数类型、个别的参数顺序)

在这里插入图片描述

2、方法覆盖的构成条件

当子类对从父类继承过来的方法进行“方法覆盖”以后,子类对象调用该方法的时候,一定是执行覆盖之后的方法。

方法覆盖的构成条件:

  • 两个类必须有继承关系
  • 重写之后的方法和之前的方法具有相同的返回值类型(后续有变)、相同的方法名、相同的形式参数列表
  • 访问权限不能更低,可以更高,如protected到public
  • 重写之后的方法不能比之前的方法抛出更多的异常

在这里插入图片描述
在这里插入图片描述

public class OverrideTest {
    public static void main(String[] args){
        Cats c = new Cats();
        Birds b = new Birds();
        c.move();
        b.move();
        b.move(1);

    }
}
class Animals{
    public void move(){
        System.out.println("动物在移动");
    }
}
class Cats extends Animals{
    public void move(){
        System.out.println("走猫步");
    }
}

class Birds extends Animals{
    //形参列表不同,这里不构成覆盖
    //相比继承的无参的方法,这里构成重载
    public void move(int i){
        System.out.println("鸟在飞");
    }
}

运行结果:
在这里插入图片描述

在这里插入图片描述

3、覆盖的注意事项

  • 覆盖是方法的覆盖,只针对于方法,和属性无关
  • 私有方法无法覆盖
  • 构造方法不能被继承,所以构造方法也无法被覆盖(所以尽管父类中有有参构造方法,子类对象也调用不了,但大家都有默认的无参构造方法)
  • 方法的覆盖只针对“实例方法”,静态方法的覆盖没有意义

在这里插入图片描述
toString()方法的输出是一个Java对象的内存地址,所以大多数时候可能需要覆盖,从而在System.out.println(引用);时,可以输出对象直观的信息,而非内存地址。

public class TestOverride {
    public static void main(String[] args) {
        MyDate date = new MyDate();
        System.out.println(date);

    }
}

class MyDate{
    private int year;
    private int month;
    private int day;

    public int getYear(){
        return this.year;
    }

    public void setTear(int year){
        this.year = year;
    }

    public int getMonth(){
        return this.month;
    }

    public void setMonth(int month){
        this.month = month;
    }

    public int getDay(){
        return this.day;
    }

    public void setDay(int day){
        this.day = day;
    }

    //this在构造方法中的用法
    public MyDate(){
        this(2022,10,27);
    }

    public MyDate(int year,int month, int day){
        this.year = year;
        this.month = month;
        this.day = day;

    }

    //覆盖默认继承类Object中的toString()方法
    public String toString(){
        //同一个类中,this省了
        return year+"年"+month+"月"+day+"日";
    }
}

toString()方法覆盖以后,不再输出对象的内存地址,输出了清晰了对象的信息
在这里插入图片描述
😉

4、多态

父类型的引用指向子类型的对象,在编译阶段绑定的是父类型的方法, 在运行阶段绑定的是子类型对象的方法,即多种形态。

在这里插入图片描述
在这里插入图片描述

public class Test {
    public static void main(String[] args){
        Animals a = new Animals();
        Birds b = new Birds();
        Cats c = new Cats();
        a.move();
        c.move();
        b.move();
        System.out.println("多态运行结果:");
        //多态
        //父类型的引用指向子类型的对象
        Animals a2 = new Birds();
        Animals a3 = new Cats();
        //无继承关系,error
        //Animals a4 = new Dog();
        a2.move();
        a3.move();



    }
}
class Animals{
    public void move(){
        System.out.println("动物在移动");
    }
}
class Cats extends Animals{
    public void move(){
        System.out.println("走猫步");
    }
}

class Birds extends Animals{
    public void move(){
        System.out.println("鸟在飞");
    }
}

class Dog{

}


在这里插入图片描述

运行结果:
在这里插入图片描述

😉


程序分析:

1 )编译阶段:

编译器只知道a2是Animals类型,所以编译器检查语法的时候,去Animals.class字节码文件中找move()方法,找到了,绑定上move()方法,编译就通过了,静态绑定成功。(编译阶段属于静态绑定)

2)运行阶段:

实际上堆内存中创建的对象是Cat对象,调用move()方法的对象是new Cat()出来的,所以运行阶段执行Cat对象的move方法,此过程为运行阶段绑定。(运行阶段属于动态绑定)
在这里插入图片描述
运行阶段和底层堆内存中的实际对象相关,执行时会自动调用实际堆内存中实际对象的相关方法。

在这里插入图片描述

5、多态之向下转型

当调用的方法是父类有的时候,如:a2.move(),静态绑定和动态绑定阶段都没问题,但当父类型的引用调用的是子类型对象中特有的方法时,静态绑定的编译阶段就会出错,此时就需要向下转型。

//向下转型的前提是有继承关系

Animals a5 = new Cats();
//用一个Cats类型的变量去装转型的Animals类型的a5
Cats x = (Cats)a5;
x.catchMouse();

向下转型成功是因为,编译器看a5是Animals类型,而要转的类Cats和Animals有继承关系,所以成功。而当一个父类有多个子类的时候,即使要转的类和实际对象的类不一样,只要有继承关系,也能转成功。

//正常new对象加一个简单的多态
Animals a6 = new Birds();

//Cats类和a6类型的Animals类有继承关系,能转型成功
Cats y = (Cats)a6;

//y是Cats类型,有catchMouse()方法,编译通过
y.catchMouse();

运行的时候,那Birds类的对象转成Cat类的对象,出错了。
在这里插入图片描述

这里是引用
经典错误—java.lang.ClassCastException,类型转换异常

在这里插入图片描述

6、instanceof–避免ClassCastException

instanceof的整理:

  • instanceof可在运行阶段动态判断引用指向的对象的类型
  • instanceof的语法:
(引用 instanceof 类型)
  • instanceof运算符的结果只能是true/false
  • 若(c instanceof Cat)结果为true,则说明引用c指向的堆内存中的对象是Cat类型,反之则说明这个引用指向的对象不是Cat类型

由此之前的ClassCastException:

Animal a6 = new Bird();
Cat y = (Cat)a6;
y.catchMouse();

可修改为:

if (a6 instanceof Cat){
	Cat y = (Cat)a6;
	y.catchMouse();
}

在这里插入图片描述

为避免ClassCastException,Java规范中要求向下转型必须使用instanceof.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思考,main方法中,我以前看到引用x指向Birds()对象,干嘛还if…else if

大项目中合作分工,若有个方法的形参是Animals a,如public void test (Aniamls a){ },调用者传入的可能是Animals类型,也可能是Birds类型、Cats类型,这就需要if+instanceof

在这里插入图片描述

7、多态在开发中的作用

作用:

  • 降低程序的耦合度
  • 提高程序的扩展力

软件在扩展新需求的过程中,修改的越少越好,修改的越多,系统的稳定性就越差,未知风险就越多,还可能得重新测试。

软件开发的原则之一就是OCP原则,即开闭原则,对扩展开放,对修改关闭,直白的说就是软件扩展的过程中,对之前的东西修改的越少越好。

在这里插入图片描述

面向抽象编程,而不是面向具体。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

😉

封装、继承、多态三个面向对象的特征环环相扣。有了封装这一整体概念之后,对象和对象之间产生了继承,有了继承之后,才有了方法的覆盖和多态。

上面多态用于程序扩展的例题中,核心是用父类型的引用做形参,调用的时候传入子类型的对象。

在这里插入图片描述

**静态方法不谈覆盖。**因为哪怕你覆盖了,并强行用”引用.“,编译时也会当类名.来处理,进而没有多态这一说,覆盖也就变的没意义了。

在这里插入图片描述

public class Override {
    //定义私有方法
    private void test(){
        System.out.println("私有的");

    }
    public static void main(String[] args) {
        Override override2 = new Override2();
        override2.test();

    }

}

class Override2 extends Override{
    //尝试给更高的权限来覆盖
    public void test(){
        System.out.println("尝试覆盖");
    }
}

运行结果不是覆盖后的test()方法;

在这里插入图片描述

私有的方法不能被覆盖,静态的方法不谈覆盖!!

在这里插入图片描述
关于方法覆盖时返回值类型,若原先是基本数据类型,则重写前后必须一致,若是引用数据类型,重写时可以变的更小,不能变的更大。(把Animals返回值类型的变成它子类型Cat的可以,变成Object类型的不行)
在这里插入图片描述
重写方法时,直接粘贴一份父类的代码过来,再修改,这样最干脆。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/146118.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!