1. 什么是方法重写?

方法重写(Override)是面向对象编程中多态性的核心体现之一。它允许子类重新定义从父类继承而来的方法,以提供更适合自身特性的实现。

核心定义:在继承关系中,子类定义一个与父类方法签名(方法名、参数列表)完全相同的方法,从而覆盖父类的原有实现。

2. 方法重写 vs 方法重载

初学者常混淆方法重写(Override)和方法重载(Overload),下表清晰对比了两者的区别:

对比维度 方法重写(Override) 方法重载(Overload)
发生位置 子类与父类之间(继承关系) 同一个类内部
方法签名 必须完全相同(方法名、参数列表) 必须不同(参数类型、个数或顺序)
返回类型 相同或是其子类(协变返回类型) 可以不同
访问权限 不能比父类方法更严格 没有限制
抛出异常 不能抛出比父类方法更宽泛的检查异常 可以不同
核心目的 实现多态,提供特定实现 提供同一功能的不同版本

3. 方法重写的规则与要求

Java 语言对方法重写有严格的语法规定,必须满足以下所有条件:

  • 签名一致:方法名、参数列表(类型、顺序、数量)必须与父类被重写方法完全相同。
  • 返回类型协变:返回类型必须相同,或是父类方法返回类型的子类(Java 5+ 支持)。
  • 访问权限不收紧:子类方法的访问修饰符不能比父类方法更严格(例如,父类是 protected,子类可以是 protectedpublic,但不能是 private 或默认包权限)。
  • 异常限制:子类方法抛出的检查异常(checked exception)不能比父类方法抛出的异常更宽泛(可以是相同异常、其子类或不抛出)。
  • 非静态、非私有、非 final:只能重写非静态、非私有、非 final 的实例方法。

使用 @Override 注解是一个好习惯,它让编译器检查该方法是否确实重写了父类方法,避免因拼写错误等原因导致意外重载。

4. 实战代码示例

下面通过一个完整的例子来演示方法重写的实际应用。

// 父类:动物
class Animal {
    // 将被重写的方法
    public void makeSound() {
        System.out.println("动物发出声音");
    }
    
    // 返回类型协变示例
    public Animal getInstance() {
        return new Animal();
    }
}

// 子类:狗
class Dog extends Animal {
    // 重写 makeSound 方法
    @Override
    public void makeSound() {
        System.out.println("汪汪汪!");
    }
    
    // 协变返回类型:返回 Dog 类型(Animal 的子类)
    @Override
    public Dog getInstance() {
        return new Dog();
    }
}

// 子类:猫
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵!");
    }
}

// 测试类
public class OverrideDemo {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog();
        Animal myCat = new Cat();
        
        // 多态调用:运行时确定具体方法
        myAnimal.makeSound(); // 输出:动物发出声音
        myDog.makeSound();    // 输出:汪汪汪!
        myCat.makeSound();    // 输出:喵喵喵!
        
        // 协变返回类型测试
        Animal animalRef = new Dog();
        Dog dogInstance = animalRef.getInstance(); // 编译通过,实际返回 Dog 对象
        System.out.println(dogInstance.getClass().getSimpleName()); // 输出:Dog
    }
}

5. 常见面试题与易错点

5.1 静态方法能被重写吗?

不能。静态方法属于类,调用时在编译期就确定了,不存在多态。子类可以定义与父类静态方法签名相同的方法,但这叫“方法隐藏”(Method Hiding),不是重写。

5.2 私有方法能被重写吗?

不能。私有方法在子类中不可见,因此无法重写。如果在子类中定义了与父类私有方法签名相同的方法,那只是一个全新的方法,与父类无关。

5.3 构造方法能被重写吗?

不能。构造方法不是继承的,每个类都有自己的构造方法。

5.4 重写时能否修改方法的访问权限?

可以放宽,但不能收紧。例如父类方法是 protected,子类可以改为 public,但不能改为 private 或默认包权限。

6. 总结

方法重写是实现运行时多态的关键机制,它让子类能够定制继承自父类的行为。掌握其规则(签名一致、访问权限、异常、返回类型协变)和与重载的区别,是深入理解 Java 面向对象编程的基础。在实际开发中,养成使用 @Override 注解的习惯,能有效避免潜在的错误。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐