首页 > 编程语言 >JavaSE--方法覆盖和多态

JavaSE--方法覆盖和多态

时间:2023-08-09 10:37:22浏览次数:38  
标签:-- move 多态 Cat public Animal JavaSE 方法 Bird

一、方法覆盖Override

1、什么时候使用Override

  例如:以下代码:鸟儿在执行move方法时,最好输出“鸟儿在飞翔”,但是当前程序在执行move方法时,输出“动物在移动”,显然Bird子类继承来的方法无法满足需求

  子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,子类有权利进行重新编写方法

public class OverrideTest{
    public static void main(String[] args){
        Bird b = new Bird();
        b.move();
        Cat c = new Cat();
        c.move();
    }
}
// 父类
class Animal{
    public void move(){
        System.out.println("动物在移动");
    }
    // protected表示受保护的,没有public开放
    protected void eat(){
        System.out.println("动物在吃");
    }
}
// 子类
class Bird extends Animal{
    // 子类继承父类之后,有一些行为可能需要进行改进
    // move重写
    public void move(){
        System.out.println("鸟儿在飞翔");
    }
    /*
        错误:正在城市分配更低的访问权限,以前为public
        protected void move(){
            System.out.println("鸟儿在飞翔");
        }
    */
    // 可以更高
    public void eat(){
        System.out.println("鸟儿在抓虫子吃");
    }
    public void sing(){
        System.out.println("鸟儿在唱歌");
    }
}
class Cat extends Animal{
    public void move(){
        System.out.println("猫猫在走路");
    }
    public void catchMouse(){
        System.out.println("猫猫抓老鼠");
    }
}

2、结论

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

3、构成方法覆盖的条件

  条件1:两个类必须有继承关系

  条件2:重写之后的方法和之前的方法具有:相同的方法名、相同的形参列表、相同的返回值类型

      注意:相同的返回值类型:对于返回值类型是基本数据类型,必须一致

                对于返回值类型是引用数据类型,可以变小,但意义不大,不会这样写

  条件3:访问权限不能更低,可以更高

  条件4:重写之后的方法不能比之前的方法抛出更多的异常,可以更少

  注意事项:注意1:方法覆盖只是针对于方法,和属性无关

       注意2:私有方法无法覆盖

       注意3:构造方法不能被继承,所以构造方法也不能被覆盖

       注意4:方法覆盖只是针对于实例方法,静态方法覆盖没有意义

4、解释:方法覆盖只是针对于实例方法,静态方法覆盖没有意义

  方法覆盖只针对实例方法,静态方法覆盖没有意义

/*
1、
    没有多态机制,方法覆盖可有可无
    没有多态机制,方法覆盖也可以没有,如果无法满足子类业务需求时,子类完全可以重新定义一个新方法
2、静态方法存在方法覆盖么?
    多态自然和对象有关系
    但是静态一般和对象没有关系
    所以一般情况下,我们会说“静态方法”没有方法覆盖
*/

public class OverrideTest05{
    public static void main(String[] args){
        Animal a = new Cat();
        a.doSome();// 输出:Animal的doSome方法
        Animal.doSome();
        Cat.doSome();
    }
}
class Animal{
    public static void doSome(){
        System.out.println("Animal的doSome方法");
    }
}
class Cat extends Animal{
    // 尝试覆盖
    public static void doSome(){
        System.out.println("Cat的doSome方法");
    }
}

5、解释:私有方法无法覆盖

  在外部类无法访问私有的

二、多态

1、向上转型与向下转型

  1)向上转型

    子----->父(可以这样叫自动类型转换)

  2)向下转型

    父----->子(可以这样叫强制类型转换,需要加强制类型转换符)

    因为自动类型转换和强制类型转换是基本数据类型之间,向上转型和向上转型是在引用类型之间

注意:java中允许向上转型也允许向下转型,但是无论哪种,两种类型之间必须有继承关系,没有继承关系编译器会报错

2、什么时候使用向下转型

  不要随便使用强制类型转换

  当你需要访问的是子类对象中“特有”的方法,此时需要向下转型

3、多态的基础语法

  父类型引用指向子类型对象

  包括编译阶段和运行阶段。编译阶段:绑定父类方法,运行阶段:动态绑定子类方法

public class Test01{
    public static void main(String[] args){
        Animal a1 = new Animal();
        a1.move();
        Cat c = new Cat();
        c.move();
        Bird b = new Bird();
        b.move();
        
        /*
            父类型的引用允许指向子类型的对象
            允许a2这个父类型引用指向子类型的对象
        */
        Animal a2 = new Cat();
        Animal a3 = new Bird();
        /*
            什么是多态
            分析a2.move();
            java程序分为编译阶段和运行阶段
            编译阶段:
                编译器只知道a2的类型是Animal,所以编译器在检查语法的时候会去Animal.class字节码文件中找move方法
                找到之后,绑定上move方法,编译通过,静态绑定成功(编译阶段属于静态绑定)
            运行阶段:
                实际上在堆内存中创建的java对象是Cat对象,所以在move时,真正参与move的对象是Cat,
                所以运行阶段会动态执行Cat对象的move方法,这个过程属于运行阶段绑定(运行阶段绑定属于动态绑定)
            多态表示多种形态:
                编译的时候时一种形态,运行的时候是一种形态
        */
        a2.move();// 猫猫在走路
        a3.move();// 鸟儿在飞翔
        
        Animal a5 = new Cat();
        // 分析程序一定要分析静态绑定和动态绑定
        // 编译不能通过,报错,编译器只知道a5是Animal类型,去Animal.class中找catchMouse没找到
        // a5.catchMouse();
        
        // 如果a5非要使用catchMouse方法,就需要使用向下转型
        // 什么时候使用向下转型:这个行为是子类型对象特有的方法
        Cat x = (Cat)a5;// 强制转换为Cat类型
        x.catchMouse();
    }
}

4、向下转型有风险,怎样避免

/*
    编译不会报错
    但是运行报错
    因为在运行阶段,堆内存中实际存放的Bird对象,但是又强制转成Cat,Bird与Cat没有继承关系
*/
Animal a6 = new Bird();
Cat y = (Cat)a6;
y.catchMouse();

   1)避免向下转型风险

  Java规范中要求:任何时候对类型进行向下转型时,一定要先使用instanceof运算符进行判断

// 怎样避免ClassCastException异常 类转换异常发生
/*
    运算符 instanceof
    第一:instanceof可以在运行阶段动态判断引用指向的对象的类型
    第二:instanceof语法
        (引用 instanceof 类型)
    第三:instanceof运算符的运算结果只能是true、false
    第四:c是一个引用,c变量保存了内存地址指向了堆中的对象
        假设(c instanceof Cat)为true表示:c引用指向的堆内存中的java对象是一个Cat
        假设(c instanceof Cat)为true表示:c引用指向的堆内存中的java对象不是是一个Cat
*/
Animal a6 = new Bird();
if (a6 instanceof Cat){// 如果a6是Cat,在强制类型转换
    Cat y = (Cat)a6;
    y.catchMouse();
}

  2)为什么要用instanceof判断

/*
    明明可以看到new的是谁,为什么还要判断呢
    原因是:有可能以后肉眼看不到
*/
Animal x = new Bird();
Animal y = new Cat();
if(x instanceof Bird){
    Bird b = (Bird)x;
    b.sing();
}else if(x instanceof Cat){
    Cat c = (Cat)x;
    c.catchMouse();
}
if(y instanceof Bird){
    Bird b = (Bird)y;
    b.sing();
}else if(y instanceof Cat){
    Cat c = (Cat)y;
}
class AnimalTest{
    public void test(Animal a){
        // 别人调用时调用test方法时传参数是穿一个Bird还是Cat
        // 别人不知道要传过来一个什么
        // Cat c = (Cat)a;
        // c.catchMouse();
        if(x instanceof Bird){
            Bird b = (Bird)a;
            b.sing();
        }else if(x instanceof Cat){
            Cat c = (Cat)a;
            c.catchMouse();
        }
    }
}

 

标签:--,move,多态,Cat,public,Animal,JavaSE,方法,Bird
From: https://www.cnblogs.com/hyy-0/p/17609773.html

相关文章

  • MySQL 管理表(增删改查)
    MySQL管理表:增加行:添加一行:insertintouservalues(42,"bbb","x",1003,1003,"teacher","/home/jingyaya3","/bin/bash");#添加所有列insertintotarena.user(name,uid,shell)values("aaa",1002,"/sbin/no......
  • 关于将预留单中增强字段带入物料凭证和会计凭证中
    1.业务需求预留中自定义文本字段“大项修”。根据预留创建物料凭证时,将该字段带入到物料凭证中,类似标准字段“项目文本”。并在物料凭证自动产生会计凭证后,将该字段带入到会计凭证行项目中。其中需要解决以上三张凭证对该字段的界面显示,以及预留对该字段的维护。解决接口中用BAP......
  • 内卷和躺平之外,职场还有其他选择
    上周写了篇文章《不要仅限于只做测试工作》,我想要表达的是不要被岗位名称和定义的职责范围困住自己,要尝试去做一些更大范围的更能锻炼自己能力的事情。后台有一位同学留言如此说道:质量保障之外潜台词里面关注效率,测试左移、右移都是在围绕提升效率和质量做文章。单系统问题......
  • rocky linux:安装ffmpeg(ffmpeg 5.1.3/rocky linux 9.2)
    一,ffmpeg官网:网址:http://ffmpeg.org/如图:说明:最新版本出到了6.0,我们从dnf通道安装,版本可能略低二,安装rpmfusion库[root@img~]#dnfinstall--nogpgcheckhttps://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm[root@img~]#dnfinstall......
  • 修改mysql8.0的数据存储目录
     -------先查看datadir的路径------------------------------------usemysqlshowvariableslike'%datadir%';————————————————————————--datadir=/data/mysqldata/mysql   老的--datadir=/bigdata/new_mysqldata  新的———————......
  • 20天 hot 100 速通计划-day05
    矩阵240.搜索二维矩阵II编写一个高效的算法来搜索*m*x*n*矩阵matrix中的一个目标值target。该矩阵具有以下特性:每行的元素从左到右升序排列。每列的元素从上到下升序排列。示例1:输入:matrix=[[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[1......
  • H5简单搭页面布局
    效果图简单总结下header:头部块标签section:中间快标签footer:底部块标签nav:通常在section下左边main:通常在section下中间部分(ie不兼容)aside:通常在section下右边article:表示独立部分和上下文无关通常在main部分 具体的结构为<header>header</header><se......
  • 研发提测前测试到底能做些什么
    作为测试,经常会遇到倒排期的项目,当研发已经占用了很多资源的情况下,此时测试要想提高效率。就不得不在研发提测前多做准备,那么研发提测前测试到底能做些什么,我将根据我的经验,在本次文章中与大家一起分享。需求分析首先要做的就是要在熟读下prd,这里面主要需要挖掘如下信息:本次......
  • spring多数据源动态切换的实现原理及读写分离的应用
    简介AbstractRoutingDataSource是Spring框架中的一个抽象类,可以实现多数据源的动态切换和路由,以满足复杂的业务需求和提高系统的性能、可扩展性、灵活性。应用场景多租户支持:对于多租户的应用,根据当前租户来选择其对应的数据源,实现租户级别的隔离和数据存储。分库分表:为了提......
  • B端页面设计
    视觉关联:当人们全身心投入到某个活动中时,会对周边干扰视而不见,这种状态被称为“流”。宜家的动线设计很好的营造了这种状态,让消费者完全沉浸于商品浏览,并且尽量不去打断这种行为流。任何一个界面呈现给用户的时候,用户都会下意识的去判断界面上什么信息是最重要的,接着会去关注这......