• 【7】Java多态:向上转型、向下转型、instanceof运算符


    一、概念

    多态,是允许不同类的对象对同一消息做出不同的响应,是面向对象最核心的特征。

    举个栗子,打印机,有黑白的打印机,可以打印黑白效果,有彩色打印机,可以打印彩色效果。

    再举个栗子,上课铃响了,上体育课的学生跑到操场上站好,上语文课的学生在教室里坐好一样。

    再再举个栗子,动物们都会叫,猫咪叫声是喵喵喵,狗叫声是汪汪汪。

    二、分类

    1)编译时多态(也叫设计时多态,举例如方法重载) 

    2)运行时多态(程序运行时决定调用哪个方法)【一般情况下在Java中提到多态指的是运行时多态。

    三、多态存在的三个必要条件

    1)要有继承关系

    2)子类要重写父类的方法

    3)父类引用指向子类对象

    四、简单理解

    如果不去理解多态的原理,就从使用的角度来讲,可以总结出了多态无非就是三句话:

    比如我们有一个父类Father,有一个子类Children

    1、向上转型是自动的。即Father f = new Children()是自动的,不需要强转

    2、向下转型要强转。即Children c = new Father()是无法编译通过的,必须要Children c = (Children)new Father(),让父类知道它要转成具体哪个子类

    3、父类引用指向子类对象,子类重写了父类的方法,调用父类的方法,实际调用的是子类重写了的父类的该方法。即Father f = new Children(),f.toString()实际上调用的是Children中的toString()方法

    参考资料:https://www.cnblogs.com/zhilu-doc/p/5338264.html

    五、向上转型&向下转型&instanceof运算符

    父类Animal 

    public  class Animal {
        //属性:昵称、年龄
        private String name;
        private int month;
    
        //无参构造
        public Animal(){
        }
        //带参构造
        public Animal(String name, int month){
            this.name=name;
            this.month=month;
        }
        //get、set方法
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getMonth() {
            return month;
        }
    
        public void setMonth(int month) {
            this.month = month;
        }
        
        //方法:吃东西
        public  void eat(){
            System.out.println("动物都有吃东西的能力");
        };
        //    方法:静态方法say
        public static void say(){//static静态方法,只能被继承,不能被重写
            System.out.println("动物间打招呼");
        }
    }
    Animal

    子类Cat

    public class Cat extends Animal {
    
        //属性:体重
        private double weight;
    
        //无参构造
        public Cat() {
    
        }
    
        //带参构造
        public Cat(String name, int month, double weight) {
            super(name, month);//调用父类构造,也可以这个写法this.setMonth(month)
            this.weight = weight;
        }
    
        //get、set方法
        public double getWeight() {
            return weight;
        }
    
        public void setWeight(double weight) {
            this.weight = weight;
        }
    
    
        //方法:跑动(cat独有的方法)
        public void run() {
            System.out.println("小猫快乐的奔跑");
        }
    
        //方法:吃东西(重写父类方法)
        @Override//快速生成重写方法快捷键CTRL+O
        public void eat() {
            System.out.println("猫吃鱼~~");
        }
        //方法:子类的静态方法,不加@Override,与父类无重写关系
        public static void say(){
            System.out.println("小猫碰胡须");
        }
    
    }
    Cat

    子类Dog

    public class Dog extends Animal{
        //属性:性别
        private String sex;
        
        public Dog(){
            
        }
        
        public Dog(String name,int month,String sex){
            this.setMonth(month);
            this.setName(name);
            this.setSex(sex);
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
        
        
        //方法:睡觉
        public void sleep(){
            System.out.println("小狗有午睡的习惯");
        }
    
        //方法:吃东西(重写父类方法)
        @Override
        public void eat() {
            System.out.println("狗吃肉~~");
            
        }
    }
    Dog

    测试类Test

    public class Test {
    
        public static void main(String[] args) {
    
            /*向上转型、隐式转型、自动转型
            Animal two=new Cat(),父类引用指向子类实例,
            可以调用子类重写父类的方法two.eat()以及父类派生的方法two.setMonth(2),
            无法调用子类独有方法two.run()
            */
            //        应用多态的实现,多种编码方式
            Animal one= new Animal() {};//1第一种,常规方法
            Animal two=new Cat();//2第二种Animal指向Cat实例
            Animal three=new Dog();//3第三种Animal指向Dog实例
            one.eat();
            two.eat();
            three.eat();
            two.setMonth(2);
            two.getMonth();
    //        two.run();//无法调用
    
            /*
            注意:父类中的静态static方法say无法被子类重写,所以向上转型之后,只能调用到父类原有的静态方法say
            如果想调用子类的say方法,可以通过向下转型转回来
            小类转型为大类
            */
            Cat cat=(Cat)two;
            cat.say();
    
    
            System.out.println("===========向上转型&向下转型分割线============");
            /*向下转型、强制类型转换
             * 子类引用指向父类对象,此处必须进行强转Cat temp=two-->Cat temp=(Cat)two,
             * 可以调用子类特有的方法
             * 必须满足转型条件才能进行强转
             * instanceof运算符:返回true/false,可以规避异常的产生
             * 判断左边的对象A是否为右边B的实例,或者对象A是否有B类的特征
             */
            if(two instanceof Cat){//如果two是Cat的实例
                Cat temp=(Cat)two;//向下转型
                temp.eat();
                temp.run();//可以调用子类独有方法
                temp.getMonth();
                System.out.println("two可以转换为Cat类型");
            }
    
            if(two instanceof Dog){
                Dog temp2=(Dog)two;//cat和dog不兼容,所以这里不能强转
                temp2.eat();
                temp2.sleep();
                temp2.getSex();
                System.out.println("two可以转换为Dog类型");
            }
    
            if(two instanceof Animal){
                System.out.println("Animal");
            }
    
            if(two instanceof Object){
                System.out.println("Object");
            }
        }
    }
    Test
  • 相关阅读:
    微信公众号对接配置
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(89)-国际化,本地化,多语言应用
    Nacos安装教程
    IDEA 中创建SpringBoot 父子模块
    解决死锁之路(终结篇)
    CentOS安装node和npm
    CentOS安装RabbitMQ
    在LibreOffice中插入代码
    PowerShell查找程序路径
    使用命令行调用控制面板的选项
  • 原文地址:https://www.cnblogs.com/haifeima/p/12968915.html
Copyright © 2020-2023  润新知