无参构造器+多态+接口与抽象类(2.2)

一、父类的无参构造器在继承关系里的作用?

1.满足子类默认构造器的隐式调用

子类中创建无参构造器时,会在第一行自动加上super(),去调用父类的无参构造器。若父类中没有无参构造器,则super()就会报错。

2.保证父类初始化流程完整

即使父类的无参构造器里什么代码都没写,JVM 也会先完成父类成员变量的默认初始化

3.支持子类对象正常实例化

当使用 new 子类()创建子类对象时,必须先触发父类构造器的执行,而父类的无参构造器就是这个执行入口。

没有这个入口,子类对象就无法被完整创建。

二、多态

1.多态性:

  • 在父类中定义的行为,被子类继承之后,表现出不同的行为。

  • 效果:同一行为在父类及其各个子类中具有不同的语义。

    引用变量既可以指向相同类型的类的对象,也可以指向该类的任何一个子类的对象。例如:Animal a = new Bird();

2.示例:

image-20260202221126239

  • 如果把子类对象赋给父类引用(将子类对象当作父类对象看待),那么就只能调用父类中已有的方法。

  • 如果子类把父类方法覆盖了,再把子类对象赋给父类引用,通过父类引用调用该方法时,调用的是子类重写之后的方法。

3.instanceof运算符:

判断对象真实类型,为向下转型做安全检查返回布尔值,避免 ClassCastException

Java编译器允许在具有直接或间接继承关系的类之间进行类型转换

image-20260202222021777

向上转型(多态):子类对象->父类引用

向下转型:父类引用->子类引用

  • 必须使用强制类型转换

  • 必须在有意义的情况下进行,即强转必须是合理的

  • 编译器对于强制类型转换采取的是一律放行的原则(只检查语义)

    例如:

    ①Bird bird = (Bird) xxx;

    无论xxx是哪种类型,编译器都不会报错。

    ②Animal animal = new Animal();
    Bird bird = (Bird)animal;

    编译无错,运行出错, ClassCastException异常

向上转型:

// 父类
class Animal {
    public void move() {
        System.out.println("动物在移动");
    }
    public void eat() {
        System.out.println("动物在进食");
    }
}

// 子类
class Bird extends Animal {
    // 重写父类方法
    @Override
    public void move() {
        System.out.println("鸟在飞");
    }
    // 子类独有方法
    public void sing() {
        System.out.println("鸟在唱歌");
    }
}

public class Test {
    public static void main(String[] args) {
        // 向上转型:父类引用指向子类对象
        Animal a = new Bird();

        // 可以调用父类的方法,运行时执行子类的重写实现
        a.move();  // 输出:鸟在飞
        a.eat();   // 输出:动物在进食

        // 不能直接调用子类独有的方法,编译报错
        // a.sing();
    }
}

向下转型:

public class Test {
    public static void main(String[] args) {
        Animal a = new Bird(); // 先向上转型

        // 1. 安全检查:判断a的真实类型是不是Bird
        if (a instanceof Bird) {
            // 2. 向下转型:把父类引用转成子类引用
            Bird bird = (Bird) a;

            // 3. 可以调用子类独有的方法
            bird.sing(); // 输出:鸟在唱歌

            // 也可以调用重写的方法
            bird.move(); // 输出:鸟在飞
        }
    }
}

总结:

向上转型做通用,让代码适配多个子类、减少重复、降低耦合,是多态的基础;

向下转型做专属,是向上转型的补充,解锁子类独有功能,实现个性化逻辑,仅在需要使用子类独有特性时才用

三、接口与抽象类

对比维度 抽象类(Abstract Class) 接口(Interface)
定义方式 使用 abstract class 关键字定义 使用 interface 关键字定义
继承 / 实现规则 子类通过 extends 单继承(一个类只能继承一个抽象类) 类通过 implements 多实现(一个类可实现多个接口);接口通过 extends 多继承其他接口
成员变量 可包含任意权限(public/protected/ 默认 /private)的变量,变量可修改 成员变量默认是 public static final(常量),必须初始化且不可修改
成员方法 可包含:- 抽象方法(abstract 修饰,无实现)- 非抽象方法(普通方法、静态方法、final 方法等,有实现) JDK8+ 可包含:- 抽象方法(默认 public abstract,无实现)- default 方法(有实现,供实现类调用或重写)- static 方法(有实现,通过接口名调用)JDK9+ 支持 private 方法(仅接口内部使用)
构造方法 有构造方法(用于子类初始化时调用,完成抽象类成员的初始化) 无构造方法(接口不存储实例状态,无需初始化)
设计定位 体现 “is-a” 关系(子类是父类的一种),用于抽取子类的共性(包含属性 + 方法),作为子类的 “模板” 体现 “like-a” 关系(类具备接口的行为),用于定义多个类的共同行为规范,作为不同类的 “协议”
实例化方式 不能直接实例化,需通过 “子类继承并完全重写抽象方法” 后,实例化子类对象 不能直接实例化,需通过 “实现类实现并完全重写抽象方法” 后,实例化实现类对象
posted on 2026-02-02 22:49  冬冬咚  阅读(0)  评论(0)    收藏  举报