当前位置: 首页 > java >正文

Java中的方法重写(Override)与方法重载(Overload)详解

一、基本概念对比

特性方法重写(Override)方法重载(Overload)
定义子类重新定义父类中已有的方法同一个类中多个同名方法,参数不同
作用范围继承关系中(父子类之间)同一个类内
方法签名必须相同(方法名+参数列表)必须不同(至少参数类型、个数或顺序不同)
返回类型相同或是父类方法返回类型的子类型(协变返回)可以不同
访问权限不能比父类方法更严格可以不同
异常抛出不能抛出比父类方法更多/更宽泛的检查型异常可以不同
静态性不能重写静态方法(隐藏不算重写)可以重载静态方法

二、方法重写(Override)

1. 重写规则

  • 必须继承关系(子类重写父类方法)
  • 方法名、参数列表必须完全相同
  • 返回类型相同或是其子类(Java 5+支持协变返回)
  • 访问修饰符不能比父类更严格(public > protected > default > private)
  • 不能抛出比父类方法更多的检查异常(非检查异常不受限)

2. 代码示例

class Animal {protected void makeSound() {System.out.println("Animal makes sound");}public Animal getInstance() {return new Animal();}
}class Dog extends Animal {// 正确重写 - 访问权限更宽松@Overridepublic void makeSound() {System.out.println("Dog barks");}// 协变返回类型 - 返回Dog而非Animal@Overridepublic Dog getInstance() {return new Dog();}
}

3. @Override注解

  • 非强制但强烈建议使用
  • 帮助编译器检查是否满足重写条件
  • 提高代码可读性
class Cat extends Animal {@Override  // 如果拼写错误会报编译错误public void makeSound() {System.out.println("Cat meows");}
}

4. 不能重写的情况

  • private方法:对子类不可见
  • final方法:禁止重写
  • static方法:属于类而非实例(可以"隐藏"但不是重写)

三、方法重载(Overload)

1. 重载规则

  • 必须在同一个类中
  • 方法名必须相同
  • 参数列表必须不同(类型、个数或顺序)
  • 返回类型可以不同(仅返回类型不同不算重载)
  • 访问修饰符可以不同
  • 可以抛出不同的异常

2. 代码示例

class Calculator {// 整数加法public int add(int a, int b) {return a + b;}// 重载1 - 参数类型不同public double add(double a, double b) {return a + b;}// 重载2 - 参数个数不同public int add(int a, int b, int c) {return a + b + c;}// 重载3 - 参数顺序不同public String add(String s, int n) {return s + n;}public String add(int n, String s) {return n + s;}
}

3. 自动类型转换与重载

class Printer {void print(int i) {System.out.println("int: " + i);}void print(double d) {System.out.println("double: " + d);}void print(String s) {System.out.println("String: " + s);}
}public class Main {public static void main(String[] args) {Printer p = new Printer();p.print(10);     // 调用print(int)p.print(10.0);   // 调用print(double)p.print("10");   // 调用print(String)p.print(10L);    // 自动转换,调用print(double)}
}

四、特殊场景分析

1. 父子类中的重载

class Parent {void process(int i) {System.out.println("Parent int: " + i);}
}class Child extends Parent {// 这是重载而非重写void process(double d) {System.out.println("Child double: " + d);}
}public class Test {public static void main(String[] args) {Child c = new Child();c.process(5);    // 调用Parent.process(int)c.process(5.0);  // 调用Child.process(double)}
}

2. 可变参数与重载

class VarArgsDemo {void process(int... nums) {System.out.println("Processing numbers");}void process(String... strs) {System.out.println("Processing strings");}// 会与上面两个方法冲突// void process(int n, String... strs) { ... }
}

3. 泛型方法重载

class GenericOverload {// 编译错误 - 类型擦除后签名相同// void process(List<String> list) { ... }// void process(List<Integer> list) { ... }// 合法重载void process(String s) { ... }void process(Integer i) { ... }
}

五、面试常见问题

1. 重写与重载的区别是什么?

  • 重写:父子类间,相同签名,实现不同
  • 重载:同类中,不同签名,功能相似

2. 构造方法能重写吗?

  • 不能,构造方法不能被继承
  • 但可以重载(一个类中多个构造方法)

3. main方法能重写或重载吗?

  • 不能重写(static方法)
  • 可以重载(但只有public static void main(String[])是入口)

4. 以下代码输出什么?

class A {void m1(Object o) { System.out.println("A"); }
}class B extends A {void m1(String s) { System.out.println("B"); }
}public class Test {public static void main(String[] args) {A a = new B();a.m1("hello");  // 输出"A"(因为m1(String)没有重写m1(Object))}
}

六、最佳实践

  1. 重写时总是使用@Override

    • 防止意外创建重载而非重写
    • 提高代码可读性
  2. 重载方法应保持功能一致

    • 不同参数形式实现相同功能
    • 避免让使用者困惑
  3. 谨慎使用可变参数重载

    • 容易导致调用歧义
    • 编译器可能无法确定最佳匹配
  4. 避免过于复杂的重载设计

    • 参数类型差异应明显
    • 考虑使用不同方法名提高可读性
  5. 注意自动装箱与重载

void process(Integer i) { ... }
void process(long l) { ... }process(5);  // 调用process(long),因为不需要自动装箱

通过深入理解方法重写和重载的区别与应用场景,可以设计出更加清晰、灵活的类结构,这是Java面向对象编程的重要基础。

http://www.xdnf.cn/news/1138.html

相关文章:

  • CSI D-PHY 散谈
  • 【Linux网络】各版本TCP服务器构建 - 从理解到实现
  • 云原生周刊:KubeSphere 平滑升级
  • UWB与GPS技术融合的室内外无缝定位方案
  • QT6 源(43):class QGroupBox : public QWidget ,最常用的容器类 QGroupBox 的源码
  • 网络编程基础
  • mybatis-plus开发orm
  • Word处理控件Spire.Doc系列教程:C# 为 Word 文档设置背景颜色或背景图片
  • 静压模型SWASH学习(9)——平底水槽高频驻波算例(Standing short wave in closed basin)
  • Django 入门实战:从环境搭建到构建你的第一个 Web 应用
  • PyTorch卷积层填充(Padding)与步幅(Stride)详解及代码示例
  • 一款丰富的工作流自动化平台 | N8N 83.6K ⭐
  • 基于外部中中断机制,实现以下功能: 1.按键1,按下和释放后,点亮LED 2.按键2,按下和释放后,熄灭LED 3.按键3,按下和释放后,使得LED闪烁
  • Android 中实现图片翻转动画(卡片翻转效果)
  • react使用01
  • 基于微信小程序的走失儿童帮助系统-项目分享
  • PerfettoSQL
  • 火山引擎实时语音合成WebSocket V3协议Python实现demo
  • redis数据类型-基数统计HyperLogLog
  • 搜索引擎的高级语法
  • 前端性能优化全攻略:JavaScript 优化、DOM 操作、内存管理、资源压缩与合并、构建工具及性能监控
  • 复刻低成本机械臂 SO-ARM100 3D 打印篇
  • RHCE 作业二(密钥登录实验)
  • XPath 语法入门
  • day35图像处理OpenCV
  • docker镜像新增加用户+sudo权限,无dockerfile
  • osxcross 搭建 macOS 交叉编译环境
  • LangChain4j 搭配 Kotlin:以协程、流式交互赋能语言模型开发
  • [特殊字符]【Qt自定义控件】创意开关按钮 - 丝滑动画+自定义样式+信号交互 | 附完整源码
  • 人工智能在PET-CT中的应用方向探析