Java中方法重载与重写的区别与避坑指南

 更新时间:2026年05月25日 08:46:04   作者:希望永不加班  
在 Java 基础面试中,重载(Overload)和重写(Override)是必考知识点;在实际开发中,二者也是实现多态、代码复用、业务扩展的核心基础,本文给大家介绍了Java中方法重载与重写的区别与避坑指南,需要的朋友可以参考下

引言

在 Java 基础面试中,重载(Overload)重写(Override)必考知识点;在实际开发中,二者也是实现多态、代码复用、业务扩展的核心基础。

但绝大多数同学只懂皮毛,分不清底层差异,经常踩坑:把重载当成重写、静态方法误判重写、协变返回混淆、参数匹配出错、多态调用失效等问题层出不穷。

一、Java 两大多态机制

想要彻底理解重载和重写,首先要搞懂 Java 的两种多态,这是二者的本质区别:

1. 静态多态(编译期多态)

程序在编译阶段就已经确定调用哪个方法,方法绑定不可更改,重载属于静态多态。

2. 动态多态(运行期多态)

程序在运行阶段根据对象的真实类型,动态绑定对应方法,重写属于动态多态,也是 Java 面向对象的核心特性。

二、方法重载(Overload)完整详解

1. 官方定义

方法重载:在同一个类中,存在多个方法名完全相同,但参数列表不同的方法,这种现象就是方法重载。

2. 触发重载的三种条件(满足其一即可)

参数列表不同,只包含以下三种情况,除此之外,所有条件都不参与重载判定

  • 参数个数不同
  • 参数类型不同
  • 参数顺序不同(不同类型参数调换顺序)

3. 合法重载代码示例

public class OverloadDemo {
    // 基础方法
    public void test(int a) {
        System.out.println("参数为int类型");
    }
    // 重载1:参数个数不同
    public void test(int a, int b) {}
    // 重载2:参数类型不同
    public void test(String a) {}
    // 重载3:参数顺序不同(不同类型)
    public void test(int a, String b) {}
    public void test(String b, int a) {}
}

4. 重载判定的「四大无关项」

很多新手踩坑:返回值、访问权限、方法异常、方法修饰符,完全不参与重载判断!

仅靠这四项不同,无法构成重载,直接编译报错!

// 错误示例:仅返回值不同,不构成重载
public void demo(){}
public int demo(){ return 1; }
// 错误示例:仅权限不同,不构成重载
public void func(){}
private void func(){}

5. 重载底层原理

编译阶段,编译器会根据方法名+参数列表生成唯一的方法签名,区分不同重载方法。

简单说:代码写完,编译完成,调用哪个方法就已经定死了,不存在运行时变化,这就是静态绑定。

三、方法重写(Override)详解

1. 官方定义

方法重写:发生在父子类继承关系中,子类对父类中非私有、非静态、非final的实例方法进行重新实现,保持方法签名一致,覆盖父类原有逻辑,实现子类个性化业务。

2. 重写五大硬性规则

1. 方法名、参数列表必须和父类完全一致

2. 权限修饰符:子类权限 ≥ 父类权限(只能放大,不能缩小)

3. 返回值:支持协变返回(引用类型可返回子类,基本类型必须一致)

4. 异常:子类抛出的受检异常,不能比父类更宽泛

  1. 5. 禁止重写的方法:private、static、final、构造方法

3. 合法重写代码示例

class Person {}
class Student extends Person {}
class Father {
    public Person getInfo() {
        return new Person();
    }
    public void say() throws Exception {}
}
class Son extends Father {
    // 合法:协变返回,返回子类类型
    @Override
    public Student getInfo() {
        return new Student();
    }
    // 合法:子类异常范围更小
    @Override
    public void say() throws RuntimeException {}
}

4. 重写底层原理

重写基于动态绑定:编译时看父类引用,运行时看真实对象类型。

JVM 在运行时通过**虚方法表(vtable)**找到子类重写后的方法执行,这也是多态的核心实现。

四、重载 & 重写 终极对比表

对比维度

重载 Overload

重写 Override

发生范围

同一个类内部

父子类继承关系中

方法名

必须相同

必须相同

参数列表

必须不同必须完全一致

返回值

无要求,不参与判定

基本类型一致,引用类型支持协变

权限修饰符

无要求

权限只能扩大,不能缩小

异常抛出

无要求

受检异常范围只能更小或相同

绑定时机

编译期静态绑定

运行期动态绑定

多态类型

静态多态

动态多态

注解支持

无专属注解

必须加 @Override 校验

五、注意事项

1:静态方法「看似重写,实则覆盖」

核心结论:静态方法不能重写,只能覆盖,多态完全失效!

class Father {
    public static void show() {
        System.out.println("父类静态方法");
    }
}
class Son extends Father {
    public static void show() {
        System.out.println("子类静态方法");
    }
}
// 测试调用
public class Test {
    public static void main(String[] args) {
        Father f = new Son();
        f.show(); // 输出:父类静态方法
    }
}

原因:静态方法属于类,不属于对象,编译期绑定父类类型,和子类无关,不存在多态。

2:参数类型不一致,误把「重载」当「重写」

这是新手最高频错误!参数细微不同,根本不是重写,是重载!

class Father {
    public void test(Object obj) {}
}
class Son extends Father {
    // 不是重写!是重载!参数类型不一致
    public void test(String str) {}
}

避坑方案:重写必须加 @Override,编译器自动校验,杜绝此类问题。

3:private 方法不存在重写

父类私有方法对子类不可见,子类同名方法是全新方法,和重写无关。

class Father {
    private void test() {
        System.out.println("父类私有方法");
    }
}
class Son extends Father {
    public void test() {
        System.out.println("子类方法");
    }
}

4:权限修饰符越改越小,编译报错

重写规则:子类访问权限不能比父类严格

权限等级:public > protected > 默认包访问权限 > private

5:受检异常范围扩大,重写失败

运行时异常无限制,受检异常必须子类 ≤ 父类,不能抛出更大范围异常。

6:可变参数与数组参数冲突,无法重载

可变参数本质是数组,二者视为同一个方法,不构成重载:

// 编译报错,冲突
public void fun(int[] arr){}
public void fun(int... arr){}

7:仅参数名称不同,不构成重载

重载只看参数类型、个数、顺序,参数名不参与判定

六、@Override 注解的核心价值

很多人以为它是摆设,其实是防坑神器

1. 强制编译器校验当前方法是否为合法重写

2. 杜绝参数写错、返回值错误、静态覆盖、权限错误等所有重写问题

3. 提升代码可读性,一眼区分普通方法和重写方法

开发规范:所有重写方法,必须添加 @Override 注解!

七、总结

重载:同类、同名不同参、编译绑定、静态多态,为了灵活适配多场景调用。

重写:父子、同名同参、运行绑定、动态多态,为了子类个性化扩展。

记住:重载看参数,重写看继承;重载编译定,重写运行变。

写在最后

重载和重写看似简单,却是 Java 面向对象、多态机制的基石,也是面试和实际开发的高频考点。很多高级特性(多态调用、框架底层封装、方法扩展)都建立在这两个特性之上。

看似基础的知识点,往往最容易藏坑。基础打牢,才能走得更远,吃透这篇,彻底告别重载重写相关bug和面试短板!

以上就是Java中方法重载与重写的区别与避坑指南的详细内容,更多关于Java方法重载与重写区别的资料请关注脚本之家其它相关文章!

相关文章

  • 详解Spring 框架中切入点 pointcut 表达式的常用写法

    详解Spring 框架中切入点 pointcut 表达式的常用写法

    这篇文章主要介绍了详解Spring 框架中切入点 pointcut 表达式的常用写法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • SpringBoot实现热部署的方式总结

    SpringBoot实现热部署的方式总结

    所谓热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用,对于Java来说,热部署就是在运行时更新Java类文件,本文将深入探讨SpringBoot有哪些方式可以实现热部署,感兴趣的朋友可以小编一探讨学习
    2023-06-06
  • 在 Spring Boot 项目中使用分页插件的两种常见方式示例详解

    在 Spring Boot 项目中使用分页插件的两种常见方式示例详解

    本文介绍了SpringBoot项目中两种分页插件的使用方法:MyBatis-Plus分页插件和PageHelper插件,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-10-10
  • Java中的接口多继承机制

    Java中的接口多继承机制

    大家好,本篇文章主要讲的是Java中的接口多继承机制,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • 详解Java spring 中类注册六种方式

    详解Java spring 中类注册六种方式

    在Spring中,将类注册为容器管理的Bean有多种方式,涵盖注解驱动、配置类、XML、动态注册等场景,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-09-09
  • Java如何在PDF中添加ToolTip工具提示

    Java如何在PDF中添加ToolTip工具提示

    大家好,本篇文章主要讲的是Java如何在PDF中添加ToolTip工具提示,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • 一篇文章弄懂JVM类加载机制过程以及原理

    一篇文章弄懂JVM类加载机制过程以及原理

    JVM原理对于初学者而言,比较晦涩难以理解,概念繁多又比较抽象,很多时候感觉看不见摸不着,还不好验证,下面这篇文章主要给大家介绍了关于如何通过一篇文章弄懂JVM类加载机制过程及原理的相关资料,需要的朋友可以参考下
    2023-02-02
  • Java数据结构之稀疏数组的实现与应用

    Java数据结构之稀疏数组的实现与应用

    这篇文章主要为大家详细介绍了Java数据结构中稀疏数组的实现与应用,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以了解一下
    2022-10-10
  • Java多线程ThreadForge的实现

    Java多线程ThreadForge的实现

    本文主要介绍了Java多线程ThreadForge的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-05-05
  • Java中的静态代码块使用解读

    Java中的静态代码块使用解读

    本文将深入探讨静态代码块的工作原理、使用场景以及一些最佳实践,帮助你更好地理解和应用这一特性
    2025-02-02

最新评论