Java 方法与重载
Java 方法声明、参数、返回值、static 与重载解析:如何把行为切成可复用、可测试的单元。
#type / concept
#status / growing
#tech / dev
#resource / java
[!info] 关联笔记
Java 方法与重载
这个概念为什么出现
若所有逻辑堆在 main,无法测试、无法复用、无法命名意图。方法把行为变成:
- 有名字的业务动作
- 有明确输入输出的边界
- 可被重载以服务不同参数形态
还要分清:重载(overload) 是同一类中签名不同;覆盖(override) 是子类重写父类方法——后者在继承篇。
[!abstract] 一句话理解 方法是类中的可执行成员;签名(名称+参数列表)决定重载选择,
static方法属于类而不绑定实例,返回类型不是重载区分依据。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:定价服务提供“按件数”和“按件数+优惠码”两种报价入口
调用方有时只有件数,有时带优惠码。用重载表达同一业务动作的不同输入,而不是 price1/price2 乱命名。
public class PricingService {
// price:基础报价(分)。
//
// 业务意图:单价 100 分 * 件数。
// 教学点:实例方法可复用内部规则。
int price(int units) {
if (units < 0) {
throw new IllegalArgumentException("units < 0");
}
return units * 100;
}
// 重载:带优惠码时减固定 50 分,但不低于 0。
// 教学点:参数列表不同 → 合法重载;返回类型相同与否不是关键。
int price(int units, String coupon) {
int base = price(units); // 复用基础规则,避免复制粘贴
if (coupon == null || coupon.isBlank()) {
return base;
}
int discounted = base - 50;
return Math.max(discounted, 0);
}
// formatMoney:静态工具方法——不依赖账户状态。
static String formatMoney(int cents) {
return cents + " cents";
}
public static void main(String[] args) {
PricingService svc = new PricingService();
System.out.println(formatMoney(svc.price(2)));
System.out.println(formatMoney(svc.price(2, "SAVE")));
}
}
建议运行:
javac PricingService.java && java PricingService
期望输出:
200 cents
150 cents
结合场景再看三个关注点
- 重载是编译期选择,依据实参静态类型。
- 复用基础方法避免两套规则漂移。
- static 适合无实例状态工具;强行 static 一切会毁掉可测试多态。
核心概念与准确模型
1. 方法声明要素
- 修饰符(
public/private/static等) - 返回类型或
void - 名称
- 参数列表
- 抛出声明(异常篇)
- 方法体
2. 签名与重载
- 重载识别主要看:方法名 + 参数列表(含顺序与类型)
- 返回类型不同不足以构成重载
- 仅参数名称不同不构成重载
3. 传参
- Java 参数传递是值传递
- 基本类型传值副本
- 引用类型传引用副本(可修改同一对象,不能让调用方变量改指向——除非返回/包装)
4. 可变参数
void log(String... lines)
- 本质接近数组
- 重载时可能模糊,需谨慎
5. 实例方法 vs static
| 实例方法 | static 方法 | |
|---|---|---|
| 调用 | 需实例(通常) | 类名或实例名(推荐类名) |
| 访问 | 可访问实例字段 | 不能直接访问实例字段 |
| 多态 | 可覆盖 | 不可按实例多态覆盖语义使用 |
边界情况与反直觉行为
- 重载 + 自动装箱/可变参数 可能导致“选了意料外重载”。
- null 实参 在多个引用类型重载间可能编译失败(歧义)。
- 递归 别忘终止条件。
常见误区
[!warning] 常见误区:重载 = 覆盖 错误理解:子类同名不同参叫覆盖。
正确模型:不同参是重载;同签名实例方法替换分派才是覆盖。
为何易错:英文 overload/override 接近。
工程实践
- 方法名用动词短语:
calculateFreight、reserveStock。 - 参数个数过多时引入参数对象。
- 保持方法短小,一个主路径意图。
- 对 public 重载做测试矩阵,防止解析意外。
本节总结
- 方法是可测试行为单元
- 重载靠参数列表区分,编译期解析
- static 与实例成员职责不同
- 为继承篇的 override 打好对比基础
自测题
- 为什么只有返回类型不同不能重载?
- 引用类型参数被方法改字段,调用方为何看得到变化?
参考答案
- 调用处可忽略返回值,编译器无法稳定仅凭返回类型消歧。
- 传递的是引用副本,仍指向同一对象,对象字段变更双方可见。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| JLS Methods | 规范 | 方法声明 |
| JLS Overloading | 规范 | 方法调用与解析 |