教程中心 / Java教程 / 继承

继承

15分钟 面向对象

什么是继承?

继承(Inheritance)是面向对象编程的三大特性之一,它是代码复用的一种重要手段。通过继承,子类可以自动拥有父类的属性和方法,同时还可以扩展自己的特有功能。

生活比喻

继承就像生物学的分类体系。"动物"是一个父类,它有"吃"、"睡"等通用行为。"狗"继承了"动物",除了有"吃"、"睡"外,还有"汪汪叫"这个狗特有的行为。"猫"也继承了"动物",有"喵喵叫"这个猫特有的行为。狗和猫 reuse(复用)了动物的基本特性。

继承的类层次结构:

                    ┌─────────┐
                    │ Object  │  ← 所有类的最终父类
                    └────┬────┘
                         │
                    ┌────┴────┐
                    │ Animal  │  ← 父类(共有属性和方法)
                    │ name    │
                    │ age     │
                    │ eat()   │
                    │ sleep() │
                    └────┬────┘
                         │
            ┌─────────────┴─────────────┐
            │                           │
       ┌────┴────┐                 ┌────┴────┐
       │   Dog  │                 │   Cat  │
       │ breed  │                 │ indoor │
       │ bark() │                 │ meow() │
       └────────┘                 └────────┘
       子类扩展父类                子类扩展父类

继承的基本语法

Java中使用extends关键字实现继承:

// 父类
class Animal {
    protected String name;
    protected int age;

    public void eat() {
        System.out.println(name + "正在吃东西");
    }

    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
}

// 子类 - 使用extends继承父类
class Dog extends Animal {
    private String breed;

    // 子类自动拥有name、age属性和eat()、sleep()方法

    public void bark() {
        System.out.println(name + "汪汪叫");  // 可以访问父类的protected属性
    }
}

// 使用
Dog dog = new Dog();
dog.name = "旺财";     // 继承自父类
dog.eat();             // 继承自父类
dog.bark();            // 子类自己的方法

super关键字详解

super关键字用于引用父类,它有三种用法:

用法说明示例
super(...)调用父类构造方法super(name, age);
super.方法名()调用父类的方法super.eat();
super.属性名访问父类的属性super.name;
class Dog extends Animal {
    private String breed;

    public Dog(String name, int age, String breed) {
        // 调用父类构造方法初始化从父类继承的属性
        super(name, age);
        // 自己特有的属性自己初始化
        this.breed = breed;
    }

    @Override
    public void eat() {
        // 先调用父类的eat方法
        super.eat();
        // 再扩展子类的特有行为
        System.out.println(name + "正在吃狗粮");
    }

    public void showInfo() {
        // 调用父类的方法
        super.showInfo();
        // 扩展子类的方法
        System.out.println("品种: " + breed);
    }
}

方法重写(Override)

子类可以重写(覆盖)父类的方法,提供自己的实现:

理解重写

方法重写就像"覆写菜单"。餐厅(父类)有一个标准菜品"红烧肉"。分店(子类)继承了这个菜品,但分店的厨师有自己独特的做法,于是"重写"了这个菜品的配方。虽然都叫"红烧肉",但吃起来味道不同。

class Animal {
    public void eat() {
        System.out.println("动物在吃东西");
    }
}

class Cat extends Animal {
    @Override  // 重写注解,编译器会检查重写是否正确
    public void eat() {
        System.out.println("猫在吃猫粮");
    }
}

// 重写规则:
// 1. 方法名、参数列表必须相同
// 2. 返回类型必须相同或是父类返回类型的子类型
// 3. 不能降低访问权限(public > protected > private)

类型转换详解

向上转型(Upcasting)

子类转换为父类类型,自动进行,绝对安全:

Dog dog = new Dog("旺财", 3, "金毛");
// 向上转型 - 自动转换,不需要强制转换
Animal animal = dog;  // 等价于: Animal animal = (Animal) dog;

// 向上转型后:
animal.eat();  // 调用的是Dog的eat()方法!多态的体现
// animal.bark();  // 错误!Animal类型看不到Dog特有的方法

向下转型(Downcasting)

父类转换为子类类型,需要强制转换,有风险:

Animal animal = new Dog("旺财", 3, "金毛");

// 向下转型 - 需要强制转换,可能ClassCastException
Dog dog = (Dog) animal;  // 安全的,因为animal确实是Dog
dog.bark();  // 现在可以调用Dog特有的方法了

// 不安全的向下转型
Animal cat = new Cat("咪咪", 2, true);
Dog dog2 = (Dog) cat;  // 运行时ClassCastException!

安全向下转型:使用instanceof检查

public void handleAnimal(Animal animal) {
    // 安全处理不同类型的动物
    if (animal instanceof Dog) {
        Dog dog = (Dog) animal;
        dog.bark();
    } else if (animal instanceof Cat) {
        Cat cat = (Cat) animal;
        cat.meow();
    } else {
        animal.eat();  // 其他动物只调用通用方法
    }
}

// Java 16+ 模式匹配(更简洁)
// if (animal instanceof Dog dog) {
//     dog.bark();
// }

继承的注意事项

单继承:Java只支持单继承(一个类只能有一个直接父类),但支持多层继承
继承内容:子类继承父类的所有非private成员(private成员子类也无法直接访问)
构造方法:构造方法不能被继承,子类需要在自己的构造方法中调用父类的构造方法
final类:使用final关键字可以防止类被继承
初始化顺序:创建子类对象时,先执行父类的构造方法,再执行子类的构造方法

Object类 - 所有类的父类

在Java中,所有类都直接或间接继承自java.lang.Object类。

Object类的方法说明
toString()返回对象的字符串表示
equals(Object obj)判断两个对象是否相等
hashCode()返回对象的哈希码
getClass()返回对象的运行时类
clone()克隆对象
finalize()垃圾回收前调用(已过时)

最佳实践

如果自定义类需要比较相等性或用作HashMap的key,应重写equals()和hashCode()方法,确保相等的对象有相同的哈希码。

小结

  • 继承使用extends关键字,实现代码复用和类层次结构
  • super用于调用父类的构造方法、方法和属性
  • 方法重写让子类提供父类方法的特定实现
  • 向上转型是安全的,自动进行,体现多态
  • 向下转型需要强制转换,可能抛ClassCastException,需用instanceof检查
  • Java只支持单继承,但支持多层继承
  • 所有类的最终父类是Object
☕ Java 在线代码编辑器
📝 运行结果