1869 字
约 6 分钟
3
第29章 Java方法重写
无标签

第29章 Java方法重写

面包屑导航 章节头部 学习目标

学习目标

  • 理解方法重写的概念和作用机制
  • 掌握@Override注解的正确使用方法
  • 学习方法重写的规则和限制条件
  • 理解多态性与方法重写的关系
  • 掌握在重写方法中调用父类方法的技巧
  • 了解方法重写的最佳实践和常见误区

方法重写概念详解

Java方法重写概念详解

方法重写(Method Overriding)是面向对象编程中的一个核心概念,它允许子类重新定义父类中已有的方法,以提供特定的实现。这是实现多态性的重要机制之一。

方法重写基础

// 父类
class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

// 子类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("狗发出汪汪声");
    }
}
  • 子类提供父类方法的特定实现
  • 必须使用相同的方法签名
  • 运行时动态绑定调用
  • 实现多态性的重要手段

@Override注解

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("猫发出喵喵声");
    }
    
    // 编译错误:方法签名不匹配
    // @Override
    // public void makeSound(String sound) {
    //     System.out.println(sound);
    // }
}
  • 编译时检查重写是否正确
  • 提高代码可读性和维护性
  • 防止因拼写错误导致的问题
  • IDE智能提示和重构支持

多态性体现

Animal[] animals = {
    new Dog(),
    new Cat(),
    new Animal()
};

for (Animal animal : animals) {
    animal.makeSound(); // 动态绑定
}

// 输出:
// 狗发出汪汪声
// 猫发出喵喵声
// 动物发出声音
  • 父类引用指向子类对象
  • 运行时确定调用哪个方法
  • 提高代码的灵活性和扩展性
  • 面向接口编程的基础

方法重写规则

方法重写规则详解

方法重写必须遵循一系列严格的规则,这些规则确保了类型安全和程序的正确性。

规则类型 具体要求 示例说明
方法签名 方法名和参数列表必须完全相同 public void method(int a)
返回类型 必须相同或是子类型(协变返回类型) String → String或Object → String
访问修饰符 不能比父类方法更严格 protected → public✓,public → private✗
异常声明 不能抛出更宽泛的检查异常 可以抛出子类异常或不抛出异常
final方法 不能被重写 public final void method()
static方法 不能被重写(可以被隐藏) public static void method()
private方法 不能被重写(子类无法访问) private void method()
构造方法 不能被重写 构造方法不是继承的一部分

代码示例

完整代码示例

/**
 * 方法重写演示程序
 * 
 * 这个类演示了方法重写的各种用法和特性
 * 包括@Override注解、多态性和方法重写规则
 */
public class MethodOverridingDemo {
    
    public static void main(String[] args) {
        System.out.println("=== Java方法重写演示 ===");
        
        // 创建不同类型的动物对象
        Animal animal = new Animal("通用动物", 5);
        Dog dog = new Dog("旺财", 3, "金毛");
        Cat cat = new Cat("咪咪", 2, "橘色", true);
        
        // 演示基本的方法重写
        System.out.println("\n=== 基本方法重写演示 ===");
        animal.makeSound();
        dog.makeSound();
        cat.makeSound();
        
        // 演示多态性
        System.out.println("\n=== 多态性演示 ===");
        Animal[] animals = {dog, cat, animal};
        for (Animal a : animals) {
            System.out.println(a.getInfo());
            a.makeSound();
            a.move();
            System.out.println("---");
        }
    }
}

/**
 * 动物基类
 */
class Animal {
    protected String name;
    protected int age;
    
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public void makeSound() {
        System.out.println(name + "发出了声音");
    }
    
    public void move() {
        System.out.println(name + "正在移动");
    }
    
    public String getInfo() {
        return "动物: " + name + ", 年龄: " + age + "岁";
    }
    
    // final方法不能被重写
    public final void sleep() {
        System.out.println(name + "正在睡觉");
    }
}

/**
 * 狗类 - 继承自Animal
 */
class Dog extends Animal {
    private String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);
        this.breed = breed;
    }
    
    @Override
    public void makeSound() {
        System.out.println(name + "(狗)发出汪汪的声音");
    }
    
    @Override
    public void move() {
        System.out.println(name + "(狗)正在快速奔跑");
    }
    
    @Override
    public String getInfo() {
        return "狗: " + name + ", 年龄: " + age + "岁, 品种: " + breed;
    }
}

/**
 * 猫类 - 继承自Animal
 */
class Cat extends Animal {
    private String color;
    private boolean isIndoor;
    
    public Cat(String name, int age, String color, boolean isIndoor) {
        super(name, age);
        this.color = color;
        this.isIndoor = isIndoor;
    }
    
    @Override
    public void makeSound() {
        System.out.println(name + "(猫)发出喵喵的声音");
    }
    
    @Override
    public void move() {
        System.out.println(name + "(猫)正在优雅地踱步");
    }
    
    @Override
    public String getInfo() {
        String environment = isIndoor ? "室内猫" : "户外猫";
        return "猫: " + name + ", 年龄: " + age + "岁, 毛色: " + color + ", 类型: " + environment;
    }
}

💻 查看完整代码 - 在线IDE体验 方法重写最佳实践

方法重写最佳实践

重写方法的编写原则

推荐做法

// 1. 总是使用@Override注解
@Override
public void method() {
    // 实现
}

// 2. 在重写方法中调用父类方法
@Override
public void process() {
    super.process(); // 保留父类行为
    // 添加子类特有逻辑
}

// 3. 保持方法的语义一致性
@Override
public String toString() {
    return "Child: " + super.toString();
}
  • 使用@Override注解确保正确重写
  • 保持方法的原始语义和契约
  • 适当调用父类方法扩展功能
  • 编写清晰的文档注释

应该避免

// 1. 不使用@Override注解
public void makeSound() { // 容易出错
    // 实现
}

// 2. 改变方法的基本语义
@Override
public void save() {
    delete(); // 语义不一致
}

// 3. 过度重写
@Override
public void method() {
    super.method(); // 不必要的重写
}
  • 不使用@Override注解
  • 改变方法的预期行为
  • 不必要的重写
  • 忽略异常处理规则

常见问题和注意事项

常见问题和注意事项

重写 vs 重载重写(Override):子类重新定义父类的方法,方法签名必须相同。重载(Overload):同一个类中定义多个同名但参数不同的方法。

访问修饰符限制重写方法的访问修饰符不能比父类方法更严格。例如,父类方法是public,子类重写方法不能是private或protected。

协变返回类型

从Java 5开始,重写方法可以返回父类方法返回类型的子类型。这被称为协变返回类型,提供了更大的灵活性。
章节总结

章节总结

  • 方法重写是面向对象编程的核心概念,实现了多态性
  • @Override注解提供编译时检查,是重写方法的最佳实践
  • 重写必须遵循严格的规则:相同方法签名、兼容返回类型、不更严格的访问修饰符
  • final、static、private方法不能被重写
  • 重写方法可以调用父类方法来扩展功能
  • 良好的重写实践能提高代码的可维护性和扩展性

导航链接 上一章:继承 章节测试 下一章:super关键字 JavaScript

第29章 Java方法重写
https://clxhxhhr.top/posts/2974/
作者
clxstart
发布于
2026-09-24
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。