文章目录

Java 继承与多态:extends 与 @Override

发布于 2026-04-03 10:35:03 · 浏览 7 次 · 评论 0 条

Java 中的继承与多态是面向对象编程的核心机制。通过 extends 关键字实现类之间的继承关系,通过 @Override 注解明确标识方法重写行为,二者协同工作,使代码具备更强的复用性与扩展性。


理解继承:用 extends 构建父子关系

创建一个父类(也称超类或基类),定义通用属性和行为。
定义子类时使用 extends 关键字继承父类,自动获得其非私有成员。

// 文件: Animal.java
public class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    public void speak() {
        System.out.println("Animal makes a sound");
    }
}
// 文件: Dog.java
public class Dog extends Animal {
    public Dog(String name) {
        super(name); // 调用父类构造器
    }
}

注意

  • 子类只能直接继承一个父类(Java 不支持多继承)。
  • 使用 super(...) 调用父类构造方法,且必须放在子类构造器的第一行。
  • protected 修饰的成员可在子类中直接访问,比 private 更开放,比 public 更安全。

实现多态:用 @Override 重写方法

多态指同一个方法调用在不同对象上表现出不同行为。要实现这一点,子类需重写(override)父类的方法。

在子类中重新定义父类已有的方法,方法名、参数列表、返回类型必须完全一致。
添加 @Override 注解,让编译器检查是否真的在重写父类方法(防止拼写错误等)。

// 继续 Dog.java
public class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    @Override
    public void speak() {
        System.out.println(name + " says Woof!");
    }
}

测试多态效果

// 文件: Main.java
public class Main {
    public static void main(String[] args) {
        Animal myPet = new Dog("Buddy");
        myPet.speak(); // 输出: Buddy says Woof!
    }
}

尽管变量 myPet 声明为 Animal 类型,但实际指向的是 Dog 对象。运行时 JVM 会自动调用 Dog 类中重写后的 speak() 方法——这就是多态。


@Override 的三大作用

  1. 明确意图:告诉其他开发者“此处是有意重写父类方法”。
  2. 编译检查:如果方法签名与父类不匹配(比如拼错方法名),编译器会报错。
  3. 防止意外遮蔽:避免因方法名相同但参数不同而无意中定义了新方法(即重载而非重写)。

删除 @Override 注解不会影响程序运行,但会失去上述安全保障。始终保留它。


常见错误与避坑指南

  1. 试图重写 privatestatic 方法

    • private 方法对子类不可见,无法重写。
    • static 方法属于类而非实例,重写无效(实际是隐藏)。
      确保被重写的方法是非 private、非 static、非 final 的。
  2. 构造器不能被重写
    构造器名字必须与类名相同,因此不存在“重写构造器”的概念。子类通过 super(...) 调用父类构造器。

  3. 返回类型协变例外
    正常情况下重写要求返回类型完全相同,但有一个例外:如果父类方法返回某个类 A,子类可返回 A 的子类。
    例如:

    class Parent {
        Object getValue() { return new Object(); }
    }
    class Child extends Parent {
        @Override
        String getValue() { return "hello"; } // 合法!String 是 Object 的子类
    }

设计建议:何时使用继承?

场景 是否推荐继承
子类确实是父类的一种(如 Dog 是 Animal) ✅ 强烈推荐
仅为复用代码而无“is-a”关系 ❌ 应优先考虑组合(has-a)
需要多继承行为 ❌ 改用接口(implements

记住:继承表达的是“是一个”(is-a)关系,不是“用得到”就继承。滥用继承会导致类层次臃肿、难以维护。


完整示例:动物叫声系统

// Animal.java
public class Animal {
    protected String name;
    public Animal(String name) { this.name = name; }
    public void speak() { System.out.println("..."); }
}

// Cat.java
public class Cat extends Animal {
    public Cat(String name) { super(name); }
    @Override
    public void speak() { System.out.println(name + " says Meow!"); }
}

// Bird.java
public class Bird extends Animal {
    public Bird(String name) { super(name); }
    @Override
    public void speak() { System.out.println(name + " chirps!"); }
}

// Main.java
public class Main {
    public static void main(String[] args) {
        Animal[] animals = {
            new Dog("Rex"),
            new Cat("Whiskers"),
            new Bird("Tweety")
        };
        for (Animal a : animals) {
            a.speak(); // 多态:各自调用重写后的方法
        }
    }
}

运行结果:

Rex says Woof!
Whiskers says Meow!
Tweety chirps!

利用数组存储不同子类对象,统一调用 speak(),无需关心具体类型——这正是多态的价值所在。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文