复习第二天多态

多态(重点)

多态 : 事物的多种形态
    举例 : 事物 -> 人 多种形态 : 黄种人,白种人,黑人,红种人
    举例 : 事物 -> 狗 多种形态 : 拉布拉多,金毛,柯基,柴犬...
    举例 : 事物 -> 水 多种形态 : 气态水蒸气,液态水,固态冰  

多态的前提条件

1. 必须有继承/实现关系 //必要条件
2. 有方法的重写 //非必要条件 -> 体现  动态绑定
3. 父引用指向子类对象 //必要条件
    Fu fu = new Zi();
        Animal animal = new Dog(); √
        Animal animal = new Cat(); √
        Animal animal = new Tiger(); √
        Dog dog = new Animal(); X
        
多态的本质 : Java中引用数据类型子父类之间的类型转换
​
类型转换:
    基本数据类型 : 前提 -> double > float > long > int > short,byte,char
        自动提升 : 小类型 --> 大类型
        强制转换 : 大类型 --> 小类型 (强制格式)
            
    引用数据类型 : 前提 -> 继承/实现 // 父类.父接口 > 子类 /实现类   
        向上转型 : 子类型  ---> 父类 
        向下转型 : 父类型 ---> 子类型

多态场景下的动态绑定问题

public class Demo {
    public static void main(String[] args) {
        Dog dog = new Dog();
        useAnimal(dog);
​
        Cat cat = new Cat();
        useAnimal(cat);
​
        Tiger tiger = new Tiger();
        useAnimal(tiger);
    }
    /*
        第一次调用时 : Animal animal  = new Dog(); -> 狗吃骨头
        第二次调用时 : Animal animal  = new Cat(); -> 猫吃鱼
        第三次调用时 : Animal animal  = new Tiger(); -> 老虎吃人
     */
    public static void useAnimal(Animal animal){
        animal.eat();
    }
}
​
interface Animal{
    public abstract void eat();
}
​
class Tiger implements Animal {
​
    @Override
    public void eat() {
        System.out.println("老虎吃人");
    }
​
​
}
​
class Dog implements Animal {
    //方法的重写
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
​
    public void lookHome(){
        System.out.println("狗看家");
    }
}
​
class Cat implements Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
​
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}

多态的弊端

弊端:
        父引用不能访问子类的特有成员!
            
    如何解决多态的弊端:
        向下转型 -> 本质是 告知父引用它是一个具体的什么对象
        格式:
            子类型 子对象 = (子类型)(父引用);
​
       傻子才会用多态的方式创建对象!! -> 子类的功能是最多的,父引用看不到子类的特有行为
            要创建对象就一定创建子类对象!            

多态的转型问题

多态的本质 : Java中引用数据类型子父类之间的类型转换
类型转换:
    基本数据类型 : 前提 -> double > float > long > int > short,byte,char
        自动提升 : 小类型 --> 大类型
        强制转换 : 大类型 --> 小类型 (强制格式)
            
    引用数据类型 : 前提 -> 继承/实现 // 父类.父接口 > 子类 /实现类   
        向上转型 : 子类型  ---> 父类 
        向下转型 : 父类型 ---> 子类型

多态的真实使用场景

n + 1种
    n : 此父类型有多少个子类型
    1 : 此父类型自己
​
1. 定义方法的时候,把父类型作为方法的形式参数类型,那么启动方法的方式有n + 1种
2. 定义方法的时候,把父类型作为方法的返回值类型,那么返回方法结果的方式有n + 1种
3. 定义容器时,把父类型作为容器的元素类型,那么容器中可以装的元素的类型有n + 1种Q
    Animal[] animals = new Animal[3];

多态向下转型的弊端

    ClassCastException : 类型转换异常
        产生的原因 : 把对象转成了不属于对象类型的对象
        如何解决: 在转型之前,做一下类型判断
              1.   instanceof : 判断类型的
                    格式 : 对象 instanceof 类型
                    作用 : 判断前面的对象是否是后面的类型 -> 返回boolean类型结果
​
              2. getClass() 和 类的class属性
                     getClass() 此方法来自于Object -> Java中所有的对象都有这个方法
                        作用是 获取此对象的字节码对象
                     每一个类都有一个类属性 叫 class -> 类名.class;
                        作用是 获取此类的字节码对象
                     而一个类 只会有一个字节码对象

匿名对象

匿名 : 没有名字
匿名对象 : 没有对象名的对象 -> 匿名对象也是对象,对象能做的它也能做
​
    格式 :  new 类名(实参);
​
匿名对象不可以重复使用!
    
   使用场景 : 如果一个对象只使用一次,那么就可以不用接收直接使用匿名对象

内部类

内部类 : 定义在类内部的类叫内部类

成员内部类(理解)

成员 : 位置关系 -> 类中方法外
成员内部类的格式:
    public class Outer{
        //成员内部类
        public class Inner{
            
        }
    }
​
    成员内部类是属于外部类的对象的!!
成员内部类的访问问题:
        1. 在内部类中访问: 内部类中可以无阻碍的访问外部类的成员
            同名的成员变量 : 就近原则
                优先访问局部
                强制访问本类成员 : this.变量名
                强制访问本类外部类成员 : Outer.this.变量名
            成员方法
                优先访问本类的 -> 每一次方法调用的前面默认隐藏 this.
                强制访问本类外部类的成员方法 -> Outer.this.方法名();
​
        2. 在外部类中访问: 无阻碍的访问外部类中的成员
            外部类中访问内部类的成员 -> 不能直接访问,必须先创建内部类的对象
​
        3. 在第三方类中访问内部类的成员  : 创建内部类的对象
                Outer.Inner inner = new Outer().new Inner();

静态成员内部类(理解)

static : 一般场景下是不可以用来修饰类的,但是当一个类变成另一个类的成员时,就可以被static修饰 
    -> 这个成员内部类就同时具备了类和成员的特点
    
格式:
    public class Outer{
        //静态成员内部类
        public static class Inner{
            
        }
    }
​
静态成员内部类是属于外部类的!!
成员内部类的访问问题: static 静态只能访问静态
    1. 把外部类的成员用 static 修饰
    2. 在内部类中创建外部类对象,使用外部类对象去点
    3. 在外部类中访问静态成员内部类的成员 就创建内部类的对象即可
    4. 在第三方类中访问静态成员内部类的成员 : 
            Outer.Inner inner = new Outer.Inner();
​
静态成员内部类使用的更多一些!!

成员内部类何时使用 : 当一个类只为另一个类服务时,可以把这个类定义在那个类的内部!!

public class Person{

public class Heart{//心脏

}

}

局部内部类(了解)

局部内部类的使用场景 : 一个类只为一个方法服务,那么就可以把这个类定义在这个方法内!
    
格式:
    public class Outer{
​
        public void method(){
            //局部内部类
            class Inner{
                
            }
        }
    }
​
局部内部类的访问问题:
        1. 在局部内部类中访问:
            无阻碍的访问内外部类的非同名成员
            强制访问外部类的同名成员 : Outer.this.成员
​
       2. 在外部类中其他方法内访问 : 访问不了!
       3. 在局部内部类所在的方法内可以访问 : 创建对象 //必须在类定义之后创建内部类对象
       4. 在第三方类中访问局部内部类成员 : 访问不了!

匿名内部类(重点)

匿名内部类(重点) : 为了更方便的使用 接口/抽象父类/普通父类的 
​
格式:
    父接口/父抽象类/父类 父引用 = new 父接口/父抽象类/父类(){
​
        //不知道类名的 实现类 / 子类 的类主体
​
    };
​
    匿名内部类的使用场景:
        1. 作为方法的实际参数传递
        2. 作为方法的返回值进行返回

权限修饰符

权限修饰符 : public > protected > 不写 > private
同一个类中 同一个包下,不同的类中 不同包下,有继承关系 不同包下,没有继承关系
public
protected
不写
private

public : 当前模块内都可以访问

private: 只能本类中访问

猜你喜欢

转载自blog.csdn.net/m0_70793154/article/details/127166322