← [ BACK_TO_NOTES ]

Java 方法与重载

Java 方法声明、参数、返回值、static 与重载解析:如何把行为切成可复用、可测试的单元。

#concept #growing #dev #java

[!info] related notes

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 Math.multiplyExact(units, 100); // 超出 int 分值范围时显式失败
    }

    // 示例规则:任意非空白优惠码减 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

结合场景再看三个关注点

  1. 重载是编译期选择,依据实参静态类型。
  2. 复用基础方法避免两套规则漂移。
  3. static 适合无实例状态工具;强行 static 一切会毁掉可测试多态。

核心概念与准确模型

1. 方法声明要素

  • 修饰符(public/private/static 等)
  • 返回类型或 void
  • 名称
  • 参数列表
  • 抛出声明(异常篇)
  • 方法体

2. 签名与重载

  • 入门看 方法名 + 形参类型列表(含顺序);泛型签名还涉及类型参数,不能仅凭 List<String> 与 List<Integer> 重载(擦除后冲突)。
  • 返回类型不同不足以构成重载
  • 仅参数名称不同不构成重载

3. 传参

  • Java 参数传递是值传递
  • 基本类型传值副本
  • 引用类型传引用副本(可修改同一对象,不能让调用方变量改指向——除非返回/包装)

4. 可变参数

void log(String... lines)
  • String... 在方法内就是 String[],且只能位于最后一个参数位置;调用方可传多个参数或直接传数组。
  • f(String...) 与 f(String[]) 不能并存为重载;零实参通常得到空数组,显式传 (String[]) null 则得到 null。

5. 实例方法 vs static

实例方法static 方法
调用需实例(通常)类名或实例名(推荐类名)
访问可访问实例字段不能直接访问实例字段
多态符合继承/访问规则且非 final 的方法可覆盖同名同签名可隐藏,不按接收对象运行时类型分派

边界情况与反直觉行为

  1. 重载分阶段匹配:先尝试不依赖装箱或变参展开的固定参数调用,再尝试装箱,最后变参;例如 int 实参在 f(long) 与 f(Integer) 之间选择前者。
  2. null 实参 在多个引用类型重载间可能编译失败(歧义)。
  3. 递归 别忘终止条件。

常见误区

[!warning] 常见误区:重载 = 覆盖 错误理解:子类同名不同参叫覆盖。
正确模型:不同参是重载;同签名实例方法替换分派才是覆盖。
为何易错:英文 overload/override 接近。

工程实践

  1. 方法名用动词短语:calculateFreight、reserveStock。
  2. 参数个数过多时引入参数对象。
  3. 保持方法短小,一个主路径意图。
  4. 对 public 重载做测试矩阵,防止解析意外。

本节总结

  • 方法是可测试行为单元
  • 重载靠参数列表区分,编译期解析
  • static 与实例成员职责不同
  • 为继承篇的 override 打好对比基础

自测题

  1. 为什么只有返回类型不同不能重载?
  2. 引用类型参数被方法改字段,调用方为何看得到变化?
参考答案
  1. 调用处可忽略返回值,编译器无法稳定仅凭返回类型消歧。
  2. 传递的是引用副本,仍指向同一对象,对象字段变更双方可见。

延伸阅读与资料来源

资料类型支撑内容
JLS Methods规范方法声明
JLS Overloading规范方法调用与解析
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本