源本科技 | 码上会

Java 中的继承

2025/12/27
27
0

学习目标

  • 理解继承的核心概念:代码复用 + “is-a” 关系

  • 掌握 Java 中通过 extendsimplements 实现单继承与多继承

  • 能够设计合理的类层次结构(单层、多层、层级)

  • 理解继承与多态、封装、抽象的协同作用

  • 避免继承使用中的常见陷阱


什么是继承

继承是面向对象编程的核心机制之一。它允许一个类(子类 / 派生类)基于另一个类(父类 / 基类)来构建,从而复用其字段和方法

核心思想:“不要重复造轮子” —— 子类自动获得父类的能力,并可扩展或定制行为。

inheritance-660x454.webp

现实类比:动物世界

  • 所有动物都会“发出声音” → 定义在 Animal 类中

  • 狗会“汪汪叫”,猫会“喵喵叫” → 各自重写 sound() 方法

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}

“is-a” 关系

  • Dog is a Animal

  • Car is a Vehicle


继承的基本语法

class 子类 extends 父类 {
    // 可添加新字段、新方法
    // 可重写(override)父类方法
}
  • 使用 extends 关键字实现类继承

  • Java 不支持类的多重继承(一个类不能 extends A, B

  • 但可通过 接口(Interface) 实现多重继承效果


继承的类型

单继承

一个子类继承一个父类。

class Vehicle {
    Vehicle() {
        System.out.println("这是交通工具");
    }
}

class Car extends Vehicle {
    Car() {
        System.out.println("这是一辆汽车");
    }
}

public class Test {
    public static void main(String[] args) {
        new Car(); 
    }
}

输出

这是交通工具
这是一辆汽车

最常用、最安全的继承形式。


多级继承

类链式继承:A → B → C

class Vehicle {
    Vehicle() { System.out.println("交通工具"); }
}

class FourWheeler extends Vehicle {
    FourWheeler() { System.out.println("四轮车"); }
}

class Car extends FourWheeler {
    Car() { System.out.println("汽车"); }
}

// 创建 Car 对象会依次调用所有父类构造器
new Car();

输出

交通工具
四轮车
汽车

注意:继承层级不宜过深(一般 ≤ 3 层),否则难以维护。


层级继承

一个父类被多个子类继承。

class Vehicle {
    Vehicle() { System.out.println("交通工具"); }
}

class Car extends Vehicle {
    Car() { System.out.println("汽车"); }
}

class Bus extends Vehicle {
    Bus() { System.out.println("公交车"); }
}

// 分别创建对象
new Car();
new Bus();

输出

交通工具
汽车
交通工具
公交车

适用于“同一类别下的多种具体类型”场景。


多重继承

仅通过接口实现

Java 不允许类多重继承,但允许一个类实现多个接口

interface LandVehicle {
    default void landInfo() {
        System.out.println("陆地交通工具");
    }
}

interface WaterVehicle {
    default void waterInfo() {
        System.out.println("水上交通工具");
    }
}

// AmphibiousVehicle 同时具备两种能力
class AmphibiousVehicle implements LandVehicle, WaterVehicle {
    AmphibiousVehicle() {
        System.out.println("两栖交通工具");
    }
}

public class Test {
    public static void main(String[] args) {
        AmphibiousVehicle v = new AmphibiousVehicle();
        v.landInfo();
        v.waterInfo();
    }
}

输出

两栖交通工具
陆地交通工具
水上交通工具

这是 Java 实现“多重继承”的唯一合法方式。


混合继承

组合多种继承类型(如:单继承 + 接口多重继承)。

class Vehicle { }

class Bus extends Vehicle { }          // 单继承

interface Fare {                       // 接口
    void chargeFare();
}

class CityBus extends Bus implements Fare {  // 混合:类继承 + 接口实现
    public void chargeFare() {
        System.out.println("公交车收费 2 元");
    }
}

Java 中的“混合继承”必须借助接口实现。


构造器调用顺序

构造器在继承中的调用顺序

  • 创建子类对象时,先调用父类构造器,再调用子类构造器

  • 若未显式调用 super(),编译器自动插入 super()

  • 若父类无默认构造器,子类必须显式调用 super(...)

class Parent {
    Parent(String msg) {
        System.out.println("Parent: " + msg);
    }
}

class Child extends Parent {
    Child() {
        super("来自子类的调用"); // 必须第一行
        System.out.println("Child 构造器");
    }
}

继承的优势

优势

说明

代码复用

避免重复编写公共逻辑(如 move(), getName()

方法重写

实现运行时多态,提升灵活性

层次化设计

体现现实世界的分类关系(如 Shape → Circle/Rectangle

易于扩展

新增子类不影响现有代码(开闭原则)


注意事项

问题

说明

紧耦合

子类高度依赖父类实现,父类变更可能破坏子类

不支持类的多重继承

无法同时继承两个具体类(为避免“菱形问题”)

滥用导致设计僵化

“继承”应表示“is-a”,而非“has-a”(后者用组合)

构造器链复杂

多层继承时初始化逻辑难以追踪

黄金法则优先使用组合,而非继承除非你确定存在清晰的 “is-a” 关系。


继承 vs 组合

场景

使用继承

使用组合

关系

“is-a”(狗 is a 动物)

“has-a”(汽车 has an 引擎)

示例

Dog extends Animal

Car { private Engine engine; }

灵活性

低(编译时绑定)

高(运行时可替换)

// 错误:用继承表示“has-a”
class Car extends Engine { } // ❌ 汽车不是一种引擎!

// 正确:用组合
class Car {
    private Engine engine; // ✅ 汽车拥有一个引擎
}

instanceof 与继承

用于检查对象是否属于某个类或其子类:

class SolarSystem { }
class Earth extends SolarSystem { }
class Moon extends Earth { }

public class Test {
    public static void main(String[] args) {
        Moon moon = new Moon();
        
        System.out.println(moon instanceof Moon);        // true
        System.out.println(moon instanceof Earth);       // true
        System.out.println(moon instanceof SolarSystem); // true
        System.out.println(moon instanceof Object);      // true(所有类继承 Object)
    }
}

用于安全类型转换前的判断。


重点总结

  • 继承通过 extends 实现,建立 “is-a” 关系

  • Java 只支持单继承,但可通过 接口实现多重继承

  • 五种继承类型:单继承、多级、层级、接口多重、混合

  • 构造器调用顺序:父类 → 子类

  • 继承促进代码复用多态实现

  • 谨慎使用继承:优先考虑组合,避免过度设计


思考题

  1. 为什么 Java 不允许类的多重继承?这解决了什么问题?

  2. 在什么情况下,使用组合比继承更合适?请举一个实际例子。

  3. 如果父类没有无参构造器,子类必须如何处理?为什么?