Java的面向对象:方法重写(0基础入门版)

一、什么是方法重写?用大白话讲透核心

先给新手最易懂的定义:
方法重写 = 子类给父类的方法"换个新逻辑" + 保留原方法名

就像生活中的例子:

  • 爸爸(父类)会做"西红柿炒蛋"(方法),步骤是"先炒蛋后炒西红柿"
  • 儿子(子类)也会做"西红柿炒蛋"(同一个方法名),但改成了"先炒西红柿后炒蛋"(新逻辑)
  • 外人喊"做西红柿炒蛋"(调用方法),爸爸和儿子会按自己的方式做,但方法名完全一样

对应到Java里:

  • 父类定义通用方法(比如eat()),子类继承后,写一个方法名、参数列表、返回值完全一样的方法,替换/扩展父类逻辑
  • 核心关键词:@Override(注解,标识这是重写方法)
  • 新手记住:重写是"父子类之间"的行为,方法名必须"一模一样",逻辑可以"全新定制"

二、为什么需要方法重写?先看反例(新手踩坑点)

先写一个「不用重写导致问题」的示例,新手一眼就能看出问题:

java 复制代码
// 父类:动物类
class Animal {
    // 通用方法:所有动物都会叫,但父类只能写通用逻辑
    public void shout() {
        System.out.println("动物发出叫声");
    }
}

// 子类:狗类
class Dog extends Animal {
    // 问题:想让狗叫"汪汪汪",但没有重写父类方法
    // 只能新增一个方法,方法名和父类不一样,逻辑混乱
    public void dogShout() {
        System.out.println("狗汪汪汪叫");
    }
}

// 子类:猫类
class Cat extends Animal {
    // 同理:新增专属方法,方法名不统一
    public void catShout() {
        System.out.println("猫喵喵喵叫");
    }
}

// 测试类
public class NoOverrideDemo {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.shout(); // 输出"动物发出叫声"(不是想要的效果)
        dog.dogShout(); // 必须调用专属方法,麻烦且不统一
        
        Cat cat = new Cat();
        cat.shout(); // 输出"动物发出叫声"
        cat.catShout(); // 调用专属方法
    }
}

问题分析

  1. 逻辑不统一:所有动物都有"叫"的行为,但子类要新增不同名的方法(dogShout/catShout),调用时没有统一标准
  2. 代码冗余:如果有10种动物,就要写10个不同名的"叫"方法,维护成本高
  3. 违背继承设计:继承的核心是"复用+扩展",但这里没有扩展父类方法,而是重新造方法

三、方法重写的核心规则(新手必记)

方法重写有5个核心规则,记准了就不会错:

  1. 方法签名完全一致:方法名、参数列表(个数、类型、顺序)、返回值必须和父类一模一样
  2. 访问权限不能更严格 :父类是public,子类不能是private/protected(新手先记:都用public
  3. 不能重写父类的private方法:父类私有的方法子类看不见,没法重写
  4. 抛出的异常不能更宽泛:(新手暂时不用记,入门阶段先关注核心规则)
  5. 建议加@Override注解:不是必须,但加了编译器会帮你检查是否符合重写规则,写错了直接报错

四、方法重写的完整代码示例(带详细注释)

java 复制代码
// 父类:动物类(定义通用方法)
class Animal {
    // 父类通用方法:动物叫(通用逻辑)
    public void shout() {
        System.out.println("动物发出叫声");
    }
    
    // 父类通用方法:动物吃食物(带参数)
    public void eat(String food) {
        System.out.println("动物吃" + food);
    }
    
    // 父类private方法:子类无法重写
    private void sleep() {
        System.out.println("动物睡觉");
    }
    
    // 父类返回值为String的方法(测试返回值一致规则)
    public String getType() {
        return "普通动物";
    }
}

// 子类1:狗类(重写父类方法)
class Dog extends Animal {
    // 1. 重写父类的shout方法(核心示例)
    @Override // 注解:标识重写,写错会报错(比如方法名写成shouts)
    public void shout() {
        // 保留父类逻辑(可选):调用父类原版方法
        super.shout();
        // 新增子类专属逻辑
        System.out.println("狗汪汪汪叫");
    }
    
    // 2. 重写带参数的eat方法
    @Override
    public void eat(String food) {
        System.out.println("狗啃着吃" + food);
    }
    
    // 3. 重写返回值为String的方法
    @Override
    public String getType() {
        return "犬类"; // 返回值类型必须和父类一致(都是String)
    }
    
    // 错误示范:试图重写父类private方法(编译不报错,但这不是重写,只是子类新增方法)
    public void sleep() {
        System.out.println("狗趴着睡觉");
    }
}

// 子类2:猫类(重写父类方法)
class Cat extends Animal {
    // 重写shout方法(纯自定义逻辑,不保留父类)
    @Override
    public void shout() {
        System.out.println("猫喵喵喵叫");
    }
    
    // 重写eat方法
    @Override
    public void eat(String food) {
        System.out.println("猫舔着吃" + food);
    }
}

// 测试类:验证方法重写效果
public class MethodOverrideDemo {
    public static void main(String[] args) {
        // ========== 测试狗类重写 ==========
        System.out.println("--- 测试狗类重写 ---");
        Dog dog = new Dog();
        dog.shout(); // 先执行父类shout,再执行子类重写的逻辑
        dog.eat("骨头"); // 执行子类重写的eat方法
        System.out.println("狗的类型:" + dog.getType()); // 执行子类重写的getType
        
        System.out.println("\n--- 测试猫类重写 ---");
        // ========== 测试猫类重写 ==========
        Cat cat = new Cat();
        cat.shout(); // 只执行子类重写的shout逻辑
        cat.eat("小鱼干"); // 执行子类重写的eat方法
        
        // ========== 测试重写规则:private方法不能重写 ==========
        System.out.println("\n--- 测试private方法 ---");
        dog.sleep(); // 执行子类新增的sleep方法,不是重写
    }
}

代码运行结果

复制代码
--- 测试狗类重写 ---
动物发出叫声
狗汪汪汪叫
狗啃着吃骨头
狗的类型:犬类

--- 测试猫类重写 ---
猫喵喵喵叫
猫舔着吃小鱼干

--- 测试private方法 ---
狗趴着睡觉

五、核心知识点解释(新手必懂)

1. @Override注解的作用(新手必加)

  • 核心作用:语法校验
    • 如果你的方法不符合重写规则(比如方法名拼错、参数列表不一样),编译器会直接报错
    • 示例:如果把@Override下的shout()写成shouts(),会提示"Method does not override method from superclass"
  • 新手理解:就像写作业时的"检查器",帮你避免低级错误

2. 方法重写vs方法重载(新手最易混淆,对比记忆)

这是Java入门最核心的两个概念,用表格对比,一看就懂:

特性 方法重写(Override) 方法重载(Overload)
发生位置 父子类之间 同一个类中
方法名 必须完全一致 必须完全一致
参数列表 必须完全一致(个数/类型/顺序) 必须不一样(个数/类型/顺序)
返回值 必须完全一致(新手阶段) 可以不一样
访问权限 不能比父类更严格 无要求
注解 可用@Override 无专属注解

3. 重写的常见场景(新手能理解)

  1. 定制化行为:父类方法是通用逻辑,子类按自己的特性修改(比如动物叫、吃食物)
  2. 扩展父类逻辑:保留父类方法的核心逻辑,新增子类专属逻辑(比如狗叫先执行父类"动物叫",再加"汪汪汪")
  3. 统一调用标准 :所有子类都重写同一个父类方法,调用时不用记不同的方法名(比如shout(),不管猫狗都能调)

4. 新手避坑点

  • 坑1:以为"方法名一样就是重写"→ 必须参数列表、返回值也一样,否则是重载或新增方法
  • 坑2:重写父类public方法时,子类写成private → 编译报错(访问权限不能更严格)
  • 坑3:试图重写父类private方法 → 其实是子类新增方法,不是重写(编译器不报错,但逻辑错了)
  • 坑4:忘记加@Override → 写错了编译器不提醒,容易埋下BUG

六、方法重写的实际应用场景(新手能理解)

  1. 框架开发 :比如SpringMVC中,你写的Controller类重写框架提供的handleRequest方法,定制自己的请求处理逻辑
  2. 工具类扩展 :比如父类是"图形工具类",有calculateArea()(计算面积)方法,子类"圆形类""矩形类"重写该方法,实现各自的面积计算
  3. 多态实现:方法重写是多态的基础(后续会讲),比如用父类引用指向子类对象,调用重写方法时,会执行子类的逻辑

七、常见面试题(新手提前了解)

  1. :方法重写的核心规则是什么?
    :方法名、参数列表、返回值必须和父类一致;访问权限不能比父类更严格;不能重写父类private方法。
  2. :@Override注解有什么用?
    :校验方法是否符合重写规则,写错时编译器报错,避免低级错误,提高代码可读性。
  3. :方法重写和方法重载的核心区别?
    :重写发生在父子类之间,参数列表必须一致;重载发生在同一个类中,参数列表必须不同。

总结

  1. 方法重写是子类对父类"同名方法"的定制化改造,核心要求是方法签名(名+参数+返回值)完全一致
  2. @Override注解是重写的"检查器",新手必须加,能避免大部分低级错误
  3. 重写和重载的核心区别:重写在父子类、参数一致;重载在本类、参数不同

新手学习建议

  1. 先复制代码运行,重点看"保留父类逻辑"和"纯自定义逻辑"两种重写方式的区别
  2. 故意写错重写规则(比如改参数列表、改访问权限),看编译器报什么错,加深记忆
  3. 练习:写一个"交通工具类(父类)→ 汽车类/飞机类(子类)",重写run()方法,实现各自的运行逻辑
相关推荐
殷紫川2 小时前
Java 工程化体系:代码规范与团队协作全链路标准
java·架构·代码规范
半瓶榴莲奶^_^2 小时前
java模式
java·开发语言
heimeiyingwang2 小时前
【架构实战】微服务架构核心概念与演进
java·微服务·架构
Memory_荒年2 小时前
当餐厅后厨也懂分布式:SpringBoot中的重试、限流、熔断与幂等的“四重奏”
java·后端·spring
我是人✓2 小时前
IDEA(2017.3 x64)的安装及使用
java·ide·intellij-idea
静心观复2 小时前
使用 new 关键字和 Java 反射创建对象的区别
java·开发语言
2601_954023663 小时前
Beyond the Hype: Deconstructing the 2025 High-Performance Stack for Agencies
java·开发语言·算法·seo·wordpress·gpl
ms_27_data_develop3 小时前
Java——集合
java·开发语言
编码忘我3 小时前
java策略模式实战之优惠券
java·后端