• 多态day02


    /*
     
            //不是多态    Student stu = new Student(); 
            //是多态      Person p = new Student(); 
        3.多态的前提:
            (1)必须要有继承或者接口实现
            (2)必须要有父类引用指向子类对象(父类类型的变量保存子类对象的地址值)
            (3)必须要有方法的覆盖重写,否则将失去多态的意义
       p = new Teacher(); 
    发现父类中: 没有kanHome方法的定义,编译报错
        4.多态的本质
            (1)就是把子类对象当成父类类型使用   父类引用指向子类对象(父类类型的变量保存子类对象的地址值) 
            (2)多态的方式调用方法,方法跟着对象走
    */ 
    
    //不使用多态弊端: 扩展性极差
    //dog = new Cat();//错误: 类型不匹配
    
    //使用多态弊端: 不能调用子类的特有行为
    //a.kanHome();
    多态中的向上转型--自动类型转换
           
       多态中的向下转型=强制类型转换
           取值范围大的数据或者变量不可以直接赋值给取值范围小的变量
           double d2 = 100;//double: 占8个字节
           int c = (int)d2;//int: 占4个字节
           强制类型转换:
               转后类型 对象名称 = (转后类型)转前的对象或者变量名称;
    注意:多
        态的向下转型(强制类型转换)存在安全隐患
           如果转换前的类型和转换后的类型不一致,就会报出类型转换异常(ClassCastException)
         
    //向下转型: 把子类对象当成子类类型使用
    Dog dog = (Dog) a;
    
    //调用特有方法
    dog.kanHome();
    /*
        强制类型转换(向下转型)存在安全隐患:
            如果转后类型和创建对象的具体类型不一致,报出类型转换异常 ClassCastException 
        如何解决呢?
            如果变量a指向的是Dog类型,把Animal类型的变量a强制转换成Dog类型
            如果变量a指向的是Cat类型,把Animal类型的变量b强制转换成Cat类型
    
        如何判断变量a指向的到底是哪种类型的对象呢?
            使用instanceof关键字
            使用格式:
                boolean result = 对象名 instanceof 类名
                    如果对象名称中保存的是该类的对象,返回true。
                    如果对象名称中保存的不是该类的对象,返回false。
    */
     
    package com.itheima;
    /*
        多态的使用场景
            使用父类类型/接口类型作为方法参数,
            调用方法时,可以传递子类/实现类对象
     */
    public class Demo10DuoTai {
        public static void main(String[] args) {
            Dog dog = new Dog();
            Cat cat = new Cat();
            showAnimal(dog);
            showAnimal(cat);
        }
        /*
             问题:
                 使用具体的子类作为方法参数的话,
                 有多少个子类,必须定义多少个方法
             解决:
                 使用父类类型作为方法参数,可以接收所有的子类对象
          */
        //定义方法,使用Animal类作为参数
        //Animal是抽象父类,必须传递子类对象
        public static void showAnimal(Animal a) {
            //调用方法
            a.eat();
            a.sleep();
            //判断引用变量a中保存的是否是Dog类的对象,如果是Dog类的对象instanceof返回true
            if (a instanceof Dog) {
                //向下转型: 把子类对象当成子类类型使用
                //把引用变量a中的内存地址,强制类型转换成成Dog类型,赋值给左侧的Dog变量dog
                Dog dog = (Dog) a;
                //调用特有方法
                dog.kanHome();
            }
    
            //判断引用变量a中保存的是否是Cat类的对象,如果是Cat类的对象instanceof返回true
            if (a instanceof Cat) {
                //向下转型: 把子类对象当成子类类型使用
                //把引用变量a中的内存地址,强制类型转换成成Cat类型,赋值给左侧的Cat变量cat
                Cat cat = (Cat)a;
                //调用特有方法
                cat.catchMouse();
            }
        }
    }
    2.定义笔记本Computer类
        成员方法: 开机功能,关机功能,使用USB接口的功能
        computer.useUSB(mouse);
        //笔记本Computer类的对象调用使用USB接口功能: 传递外部设备键盘KeyBoard类的对象
        computer.useUSB(keyBoard); 
    //方法参数是接口: 调用方法时必须传递接口实现类对象
    //方法被调用时: USB usb = 0x666 = new Mouse() 多态(左侧是接口变量,右侧是实现类对象)
    /*
        final关键字: 代表最终的,不可改变
            可以修饰的内容:
            1.类:
                不可以被继承,不能够有子类
                看: MyString和MyArrayList
                称之为太监类: 不能有子类,但是有父类
            2.方法:
                不能被子类覆盖重写
    
            3.变量:   只能赋值一次,不可以进行第二次赋值,变量的值是不可以发生改变的     常量
            //错误: Fu01被final修饰,不可以被继承
            public MyArrayList(Collection c) {   super(c); }
     */
    /*
    //被final修饰的方法: 不能被子类覆盖重写  
        子类重写后的方法上,可以添加final
        意思: 子类的方法功能已经很完善了,如果有孙子类,不允许重写该方法
     */
    @Override
    public /*final*/ void fun() {
        System.out.println("Zi02...fun...");
    }
    public class MyClass03 {
        String name;
        final int num;//定义未初始化
        final int num2 = 10;//定义并初始化
    
        //注意: 构造方法是在对象创建完毕后(此时对象的成员变量已经有值了)执行的
        //空参构造
        public MyClass03() {
            //错误: 不能第二次赋值
            //num2 = 100;
            //正确: 第一次赋值
            num = 200;
        }
    
        //有参构造
        public MyClass03(String name,int num) {
            this.name = name;
            //正确: 第一次赋值
            this.num = num;
            //错误: 不能第二次赋值
            //num2 = 100;
        }
    
        //成员方法: 必须由对象调用,对象都有了,成员变量也已经有值了吧
        public void method() {
            //错误: 不能第二次赋值
            //num2 = 100;
            //错误: 不能第二次赋值
            //num = 2000;
        }
    }
    
    package com.itheima.d3_final_var;
    
    import java.util.Arrays;
    
    /*
        final修饰变量:
            1.特点: 只能赋值一次,不可以进行第二次赋值,变量的值是不可以发生改变的     常量
            2.修饰局部变量(方法内部定义的变量):
                (1)基本类型: 基本类型变量中存储的具体的数字是不可以被改变的
    
                (2)引用类型: 存储的对象的地址值,被final修饰后,说明变量存储的对象的地址值是不可以被改变的
                                    但是该地址代表的内存空间中的内容是可以改变的
    
            3.成员变量: 看MyClass03 认为默认值无效,要么显式赋值,要么构造方法中赋值
                (1)定义未赋值: --看MyClass03中的num
                    所有构造方法中,必须完成对final修饰的变量的赋值
                    所有成员方法中,不能修改final修饰的变量的值
    
                (2)定义并赋值: --看MyClass03中的num2
                    所有构造方法/成员方法中,不能修改final修饰的变量的值
     */
    public class Demo03FinalVar {
        public static void main(String[] args) {
             
            //final修饰引用类型(数组)局部变量
            final int[] array = new int[]{10, 20};
            System.out.println(Arrays.toString(array));
            //把数组的每个元素扩大10倍
            //错误: 数组变量array被final修饰后,说明内部保存的内存地址值不可以发生改变
            //array = new int[]{100, 200};
            for (int i = 0; i < array.length; i++) {
                //只是通过原有地址找到数组,修改元素值,但是并没有修改内存地址值
                array[i] *= 10;
            }
            System.out.println(Arrays.toString(array));
            System.out.println("----------------");
    
            //final修饰引用类型(类)局部变量
            final Student stu = new Student("张三", 18);
            stu.show();
            //两年后,年龄增加两岁
            //错误: 引用变量stu被final修饰后,说明内部保存的内存地址值不可以发生改变
            //stu = new Student("张三", 20);
            //只是通过地址找到对象,修改成员变量的值,但是并没有修改内存地址值
            stu.setAge(stu.getAge() + 2);
            stu.show();
        }
    
        public static void change(final int a, final int b) {
           /* a*=10;
            b*=10;*/
        }
    }
    
    //使用四种不同的权限修饰符定义变量
    public int a = 1;
    protected int b = 11;
    int c = 111;
    private int d = 1111;
    //不同包的无关类: 只有public可以使用,其余无法使用
    //不同包子类: 除了private和默认以外都可以使用
    //同一个包子类: 除了private以外都可以使用
    /*
        权限修饰符                   public          protected           默认(什么都不写)           private
        在同一个类中                   √                  √                   √                       √
        在同一个包中(子类/无关类)      √                  √                   √
        不同包的子类                   √                  √
        不同包的无关类                 √
     */
  • 相关阅读:
    【C++】类和对象(中)
    源码分析:调度器 schedul 开发
    即时零售业态下如何实现自动做账?
    云原生系列 【基于CCE Kubernetes编排实战】
    使用watch和tail命令监控文件内容的变化
    Mac电脑配置Flutter开发环境
    算法学习笔记(3.1): ST算法
    C++重载输入和输出运算符
    【首测】两款OpenCV 人工智能深度相机OAK PoE
    记一次服务器异常掉电,导致HBase Master is initializing 问题处理
  • 原文地址:https://blog.csdn.net/qq_35744728/article/details/125629944