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

结合场景再看三个关注点

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

核心概念与准确模型

1. 方法声明要素

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

2. 签名与重载

  • 重载识别主要看:方法名 + 参数列表(含顺序与类型)
  • 返回类型不同不足以构成重载
  • 仅参数名称不同不构成重载

3. 传参

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

4. 可变参数

void log(String... lines)
  • 本质接近数组
  • 重载时可能模糊,需谨慎

5. 实例方法 vs static

实例方法static 方法
调用需实例(通常)类名或实例名(推荐类名)
访问可访问实例字段不能直接访问实例字段
多态可覆盖不可按实例多态覆盖语义使用

边界情况与反直觉行为

  1. 重载 + 自动装箱/可变参数 可能导致“选了意料外重载”。
  2. null 实参 在多个引用类型重载间可能编译失败(歧义)。
  3. 递归 别忘终止条件。

常见误区

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

工程实践

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

本节总结

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

自测题

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

延伸阅读与资料来源

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