多态 【掌握】
什么是多态
是一个事物表现出来的多种形态
猫/狗 也可以说是动物
摩托车 也可以说是机动车
学生 也可以说成是人

        面试题:以下诗词体现的是面向对象的哪种特征
            苏轼曰:横看成岭侧成峰,远近高低各不同

            体现了多态的特征


    在Java中的多态,是一个对象表现出来的多种形态
        // 狗是狗
        Dog d = new Dog();
        // 狗是动物,体现了多态
        Animal a = new Dog();

        体现在:父类的引用指向子类的对象
                父类类型的变量去记录子类对象的地址


多态的前提
    1、有继承/实现关系
    2、一般会有方法重写
    3、父类的引用指向子类的对象
        接口的引用指向实现类的对象

多态下的成员访问特点
    成员变量
        编译看左边(父类),运行看左边(父类)

    成员方法
        非静态的成员方法
            编译看左边(父类),运行看右边(子类)
        静态的成员方法
             编译看左边(父类),运行看左边(父类)

    总结:编译都看左边(父类),只有非静态的成员方法运行的时候看右边(子类),其余都看左边

多态的优缺点
    优点:
        提高程序扩展性

    缺点:
        无法使用子类特有成员

多态的类型转换
    这里的类型转换指的是引用类型的转换,基础班学习的类型转换是基本类型的转换
    向上转型:类似于基本类型转换中的隐式转换/自动类型提升,子类类型转换为父类类型,父类引用指向子类对象就是向上转型
            Animal a = new Dog();
    向下转型:类似于基本类型转换中的强制转换,父类类型转换为子类类型
                子类类型 变量名 = (子类类型)父类类型的值;
                Dog d = (Dog)a;

向下转型中的问题和解决
    类型转换异常:ClassCastException

    解决:先判断,是这种类型,再转换
        判断:instanceof运算符

        boolean flag = 对象(名) instanceof 类;


多态的应用场景
    1、创建的对象时候
         Animal a = new Cat();
         private BaseStudentDao studentDao = StudentDaoFactory.getStudentDao();

    2、方法参数传递
        public static void useAnimal(Animal a){

        }

        useAnimal(new Dog());
        useAnimal(new Cat());

    3、方法的返回值
        public static BaseStudentDao getStudentDao() {
            return new StudentDao();
    //        return new OtherStudentDao();
        }


方法的参数传递:方法要什么类型就传什么类型,要几个参数就传几个参数
参数是基本类型
参数是引用类型
    数组
    类:Student Dog Animal String
    接口:Jump Inter BaseStudentDao List

    如果形参是数组,就传递对应类型的数组对象即可
    如果形参是类类型,就传递该类的对象,或者该类的子类对象
        如果类是一个抽象类,则只能传递该类的子类对象,因为抽象类无法创建对象
    如果形参是接口类型,则只能传递该接口的实现类对象,因为接口无法创建对象

内部类
成员内部类 【了解】
直接定义在类中方法外的类,在类的成员位置定义的
注:以后我们基本上不会编写和使用成员内部类,只要以后查看源码看到了能知道这是内部类即可

    内部类的访问特点
        内部类可以直接访问外部类的成员,包括私有
        外部类要访问内部类的成员,必须创建对象
    外界创建成员内部类格式
        格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
        举例:Outer.Inner oi = new Outer().new Inner();

    可以在类中直接定义的内容
        成员变量
        成员方法
        构造方法
        成员内部类(内部接口、内部枚举)
        代码块(静态代码块、构造代码块)

局部内部类               【了解】
    直接定义在方法中的类,在类的局部位置定义的
    注:以后我们基本上不会编写、使用成员内部类,甚至见都见不到



匿名内部类               【掌握】
    什么是匿名内部类
        就是一个没有名字的局部内部类

    作用
        简化代码块,将类的继承/实现、方法重写、对象创建者三步一起完成

    格式
        new 类/接口名() {

            // 方法的重写或者实现
        };


        类/接口类型 变量名 = new 类/接口名() {

            // 方法的重写或者实现
        };


        匿名对象:没有名字的对象,没有变量引用的对象
                    new Student();
        匿名内部类:没有名字的类
            匿名内部类的匿名对象:创建的匿名内部类的对象没有使用一个变量来接收这个对象


    原理
        匿名内部类是在创建该类的子类对象,或者创建该接口的实现类对象


    匿名内部类的使用场景
        一切需要该类的子类对象,或者该接口的实现类对象的场景大部分都是可以使用匿名内部类的

        1、调用方法当做实参
        2、当做方法的返回值
        3、直接多态的方式创建该类的子类对象,或者该接口的实现类对象

Lambda表达式
作用:简化代码,可以对部分匿名内部类的代码做进一步的简化

Lambda表达式的使用前提
    1、必须是一个接口
    2、这个接口中有且只有一个抽象方法

    有且只有一个抽象方法的接口,称之为函数式接口(FunctionalInterface)
    可以通过一个@FunctionalInterface注解来验证接口是否是函数式接口

    Lambda表达式的原理:创建接口的实现类对象

Lambda表达式的格式
    标准格式
        () -> {}

        ():指的是接口的抽象方法的形式参数
        ->:传递的意思,固定的格式
        {}:实现了抽象方法之后的方法体内容

    省略格式
        () -> {}
        规则:
          ():
            0个参数:小括号不能省略
            1个参数:小括号和数据类型可以省(如果要省略小括号,则一定要省略数据类型)
            2个及其以上参数:只能省略数据类型,不能省略小括号

          ->:不能省略

          {}:
            只有一行语句的时候才可以省略,可以省略{}、return和语句结尾的分号,要省则三者同时省
            如果一行以上的语句则不可以省略