当方法名相同时:重载与重写的实战抉择
日期:2025-05-28 03:47:49 •原创
一、点咖啡引发的编程思考
那天在星巴克听到这样的对话:
"我要大杯冰美式"
"我要中杯热拿铁"
"我要超大杯去冰摩卡"
突然意识到,这场景不就是活生生的??方法重载??吗?你看,服务员就像Java虚拟机,通过??参数类型(杯型)??和??参数组合(温度+品类)??自动选择对应处理方法。让我们把这个场景写成代码:
java复制class CoffeeMaker { // 重载方法1:基础款 public void makeCoffee(String size) { System.out.println("制作" + size + "标准美式"); } // 重载方法2:定制款 public void makeCoffee(String size, String temperature) { System.out.println("制作" + temperature + size + "定制咖啡"); } // 重载方法3:顶配款 public void makeCoffee(String size, String temperature, String type) { System.out.println("制作" + temperature + size + type); } }
??开发启示:??
- 重载就像咖啡店的菜单扩展,保持核心功能(制作咖啡)不变
- 通过参数差异(数量/类型)自动匹配最佳方案
- 千万别学某些咖啡师把"大杯"写成"Large"而"中杯"用"Mid",要保持参数类型统一性
二、餐厅点餐系统升级的教训
某连锁餐厅的旧系统是这样的:
java复制class OrderSystem { public void processOrder() { // 固定处理堂食订单 } }
当需要扩展外卖功能时,菜鸟程序员A直接修改原方法,导致线上订单全部出错。而高手程序员B的选择是:
java复制class NewOrderSystem extends OrderSystem { @Override public void processOrder() { if(isTakeout) { // 处理外卖逻辑 } else { super.processOrder(); // 复用堂食逻辑 } } }
??这就是方法重写的典型场景:??
- 发生在继承关系的父子类之间
- 方法名、参数、返回类型完全一致
- 用
@Override
明确声明覆盖意图 - 就像餐厅升级POS系统,保留基础功能,扩展新业务
三、支付系统踩坑实录
最近帮朋友公司排查的诡异Bug:
java复制class Alipay { public void pay(BigDecimal amount) { // 支付宝支付逻辑 } } class WechatPay extends Alipay { public void pay(Double amount) { // 自以为在重写父类方法 // 微信支付逻辑 } }
当调用new WechatPay().pay(new BigDecimal("100.00"))
时,竟然走了父类的支付宝通道!??问题根源:??
- 参数类型从BigDecimal变成Double,这不叫重写而是重载
- 正确做法应该保持参数类型一致:
java复制class WechatPay extends Alipay { @Override public void pay(BigDecimal amount) { // 真正的重写 // 微信支付逻辑 } }
??避坑指南:??
- 重写就像银行卡换芯片,卡号(方法签名)不能变,只是内部技术升级
- 用IDE的
@Override
注解自动校验是否成功覆盖 - 涉及钱的计算永远用BigDecimal,别用double埋雷
四、开发场景决策流程图
遇到方法扩展需求时,用这张图快速决策:
? ? ? ? ? ? ? ? ? ? ? ┌───────────┐
? ? ? ? ? ? ? ? ? ? ? │ 需要修改父类行为? │
? ? ? ? ? ? ? ? ? ? ? └─────┬─────┘
? ? ? ? ? ? ? ? ? ? ? ? ? ? ↓
? ? ? ? ? ? ? ? ? ┌─────────┴─────────┐
? ? ? ? ? ? ? ? ? │是 ? ? ? ? ? ? ? ? 否│
? ? ? ? ? ? ? ? ? ↓ ? ? ? ? ? ? ? ? ? ↓
? ? ? ┌─────────────────────┐ ? ┌───────────────┐
? ? ? │使用重写 ? ? ? ? ? ? │ ? │参数类型/数量不同? │
? ? ? │1.保持方法签名一致 ? ? │ ? └──────┬──────────┘
? ? ? │2.用@Override注解 ? ? │ ? ? ? ? ? ↓
? ? ? └─────────────────────┘ ? ┌───────┴───────┐
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? │是 ? ? ? ? ? ? 否│
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ↓ ? ? ? ? ? ? ? ↓
? ? ? ? ? ? ? ? ? ? ? ┌───────────────────┐ ? ┌────────────┐
? ? ? ? ? ? ? ? ? ? ? │使用重载 ? ? ? ? ? │ ? │新建独立方法 │
? ? ? ? ? ? ? ? ? ? ? │1.同方法名 ? ? ? ? │ ? │避免混淆 ? ? │
? ? ? ? ? ? ? ? ? ? ? │2.参数列表不同 ? ? │ ? │ ? ? ? ? ? │
? ? ? ? ? ? ? ? ? ? ? └───────────────────┘ ? └────────────┘
五、从Spring框架看实际应用
在SpringBoot中,重写@Bean
方法是个典型场景:
java复制@Configuration class DatabaseConfig { @Bean public DataSource dataSource() { return new HikariDataSource(); // 默认数据源 } } @Configuration class CloudDatabaseConfig extends DatabaseConfig { @Override @Bean public DataSource dataSource() { // 重写为云数据库 return new CloudDataSource(); } }
??而MyBatis的XML映射文件解析,则大量使用重载:??
java复制class SqlSessionTemplate { public
T selectOne(String statement) {...} public T selectOne(String statement, Object parameter) {...} public T selectOne(String statement, Object parameter, RowBounds rowBounds) {...} }
个人编程哲学
做了这么多年Java开发,我有个固执的坚持:??能用重载解决的问题,就不要用重写??。就像手机系统升级,能通过安装新APP(重载)实现的功能,就别轻易刷机(重写系统方法)。特别是在维护祖传代码时,重载的扩展性比重写更安全——毕竟谁也不想成为那个把java.util.Date
的toString()
方法重写后引发全线崩溃的倒霉蛋。
本文由嘻道妙招独家原创,未经允许,严禁转载