当前位置:网站首页>多态day02

多态day02

2022-07-06 02:57:00 大厂全栈

/*
 
        //不是多态    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
    在同一个类中                   √                  √                   √                       √
    在同一个包中(子类/无关类)      √                  √                   √
    不同包的子类                   √                  √
    不同包的无关类                 √
 */
原网站

版权声明
本文为[大厂全栈]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_35744728/article/details/125629944