Day10——多态、内部类

多态

面向对象三大特性:封装、继承、多态

向上造型

1)超类型的引用 Animal ani 指向派生类的对象 new Dog()(即前父后子)

java认为父类大,子类小,所以子类向父类转换类似自动类型转换,称为向上造型

class Animal{}
interface Swim(){}
class Dog extends Animal implements Swim{}

Animal ani = new Dog();//Dog继承于Animal,向上造型
Dog d = new Animal();//编译错误

2)能点出(直接访问)什么,看引用的类型 Animal ani

当对象展现的形态不同,所能拥有的属性和行为也不同,这就是多态

Animal ani = new Dog();//只能点出Animal类中的属性或行为
ani.eat();//只能调用Animal类中的属性和方法

3)可以向上造型成为的类型有:所继承的父类、所实现的接口

Animal ani = new Dog();//向上造型所继承的父类
Swim s = new Dog();//向上造型实现的接口 

向上造型的应用场景

  • 传参时传入父类,相当于将父类及其子类全部传入,调用该方法时可以new任意子类对象

    /**
     * 主人类,可以喂养动物
     */
    public class Master {
        void feed(Animal animal){ //传入Animal父类,传参时可以传Animal类及其子类
            animal.eat();
        }
        public static void main(String[] args) {
            Animal animal01 = new Dog("旺财", 3, "红");
            Animal animal02 = new Chick();
            Animal animal03 = new Fish();
            Master master = new Master();
            master.feed(animal01);//喂狗
            animal01.eat();
            master.feed(animal02);//喂鸡
            master.feed(animal03);//喂鱼
        }
    }
    
  • 将父类作为方法返回值类型,可以将方法的返回值扩大到父类及其子类的所有类型

  • 扩大引用类型数组范围

    定义父类的引用类型数组,其中既可以装父类对象,也可以装其所有子类对象

    [!IMPORTANT]

    注:此方式不能访问各子类的特有属性和行为

    Animal[] animals = new Animal[10];
    animals[0] = new Dog();//只能访问Animal中的属性和行为
    animals[1] = new Chick();
    animals[2] = new Fish();
    

向下转型

相当于强制类型转换,父类到子类,从大到小

向上转型时父类无法访问子类的属性和行为,若想访问的属性和行为在父类中没有时,须向下转型

若父类中有需要的属性和行为,则不需要转

向下转型成功的条件:

强转时若不满足以下条件,则发生ClassCastException类型转换异常

[!TIP]

强转前通过instanceof判断引用指向的对象是否是该类型,为true则是强转成功的条件

  • 引用所指向的对象就是该对象
  • 引用所指向的对象实现了该接口或继承了该类
Animal dog = new Dog();
if (dog instanceof Dog){ //true
    Dog dog1 = (Dog)dog; //引用dog所指向的对象Dog,就是Dog当前类型
}
if (dog instanceof Swim){ //true
    Swim swimDog = (Swim)dog;//引用dog所指向的对象Dog,实现了Swim接口
}

内部类

内部类在编译时也会生成独立的.class字节码文件

内部类生成.class字节码文件

成员内部类

类中套类,外面的成为外部类,里面的为内部类

  • 内部类通常只服务于外部类,即实例化时只能new外部类,内部类无法在main中实例化(对外不可见)

    class Aoo{
        void func(){
            new Boo;//只能在外部类中访问内部类
        }
        class Boo{
            
        }
    }
    
  • 内部类中可以直接访问外部类的成员

    内部类中有个隐式的引用指向了创建它的外部类对象(外部类名.this)

    class Aoo{
    	int num;
        class Boo{
            System.out.println(num);//内部类直接访问外部类成员变量
            System.out.println(Aoo.this.num);//完整写法
        }
    }
    

匿名内部类

若想创建一个派生类的对象,且对象只创建一次,可以设计为匿名内部类

匿名内部类只能创建一次

创建过程:

  1. 创建一个Inter的匿名派生类,即创建一个实现了Inter的没有名字的类(不可见)

  2. 为该派生类创建了一个对象o1,并向上造型为Inter类型

    new Inter(){}; 是在创建Inter派生类的对象

    {} 中为Inter派生类的类体

public class AnnoInnerClassDemo {
    public static void main(String[] args){
        Inter o1 = new Inter(){};//匿名内部类
    }
}

interface Inter(){
    
}

匿名内部类的使用

public class AnnoInnerClassDemo {
    public static void main(String[] args) {
        Inter inter01 = new Inter(){
            @Override
            public void show() {
                System.out.println("show inter01");
            }
        };
        Inter inter02 = new Inter(){
            @Override
            public void show() {
                System.out.println("show inter02");
            }
        };
        inter01.show();
        inter02.show();
    }
}
interface Inter{
    void  show();
}

[!IMPORTANT]

注:

  • 匿名内部类中不允许修改外部变量的值(main方法中的局部变量),内部类中变量默认带 final 修饰符
  • 匿名内部类中是否允许访问外部变量的值,各个jdk版本规定不同
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值