定义

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

修饰符 + 返回类型 + 名字 + 参数列表 + 体。

静态 vs 实例

public class Util {
    public static int square(int x) {        // 静态:属于类
        return x * x;
    }

    public int doubled(int x) {              // 实例:需要对象
        return x * 2;
    }
}

// 调用
Util.square(5);                              // 静态:用类名
var u = new Util();
u.doubled(5);                                // 实例:用对象

静态方法:不依赖对象状态、就是一个普通函数式工具。

访问修饰符

谁能调用
public 任何代码
protected 同包 + 子类
(默认 / 包私有) 同包
private 本类

默认 private——除非有理由开放。

重载(同名多版本)

public int add(int a, int b) { return a + b; }
public double add(double a, double b) { return a + b; }
public String add(String a, String b) { return a + b; }
public int add(int a, int b, int c) { return a + b + c; }

按参数类型 / 数量自动选——叫重载分辨

只返回类型不同不是重载——编译错。

varargs(可变参数)

public static int sum(int... nums) {     // ... 表示可变数量
    int total = 0;
    for (int n : nums) total += n;
    return total;
}

sum();                          // 0
sum(1, 2, 3);                   // 6
sum(1, 2, 3, 4, 5);             // 15

int[] arr = {1, 2, 3};
sum(arr);                       // 也可以传数组

int... nums 在方法里是 int[]varargs 必须是最后一个参数

默认参数?

Java 没有默认参数。用重载模拟:

public void greet(String name, String greeting) { ... }
public void greet(String name) { greet(name, "Hello"); }
public void greet() { greet("World", "Hello"); }

或用 Builder 模式(第 09 篇构造函数 提)。

命名参数?

Java 也没有。可读性方案:

// 用对象(builder 或 record)
sendEmail(EmailRequest.builder()
    .to("a@x.com")
    .subject("Hi")
    .body("Hello")
    .build());

// 或简单 record(Java 14+)
record EmailRequest(String to, String subject, String body) {}
sendEmail(new EmailRequest("a@x.com", "Hi", "Hello"));

详见 第 12 篇 records

返回值

public int compute() { return 42; }         // 必须 return
public void doIt() { System.out.println(); } // void 不返回

// 多个出口
public String classify(int n) {
    if (n < 0) return "负";
    if (n == 0) return "零";
    return "正";
}

返回 Optional 还是 null

public User findById(int id) {
    User u = db.find(id);
    return u;       // 可能 null
}

// vs

public Optional<User> findById(int id) {
    User u = db.find(id);
    return Optional.ofNullable(u);   // 显式可空
}

// 调用方
var maybe = repo.findById(1);
maybe.ifPresent(u -> System.out.println(u.getName()));
var name = maybe.map(User::getName).orElse("anonymous");

新代码倾向 Optional 返回——签名就告诉调用方"可能没结果"。详见 第 16 篇

不要用 Optional 做字段 / 参数——Optional 是"可能不存在的返回值"的语义,其他场景反而别扭。

抛异常

public void withdraw(double amount) {
    if (amount <= 0) throw new IllegalArgumentException("金额必须 > 0");
    if (amount > balance) throw new InsufficientFundsException(balance, amount);
    balance -= amount;
}

详见 第 19 篇

受检异常(checked exception)

public String read() throws IOException {
    return Files.readString(path);
}

// 调用方
try {
    var s = read();
} catch (IOException e) {
    ...
}

抛受检异常(继承 ExceptionRuntimeException)的方法必须 throws 声明。Java 独有,C# / Kotlin / Python / JS 都没有。

现代 Java 风格:少用受检异常——业务代码用 RuntimeException 子类。受检异常对 API 调用方束缚大,常被吐槽。

final 参数

public void process(final int x, final List<String> list) {
    // x = 5;       // ❌ 不能改
    // list = ...;  // ❌ 不能改引用
    list.add("ok"); // ✅ 内容能改(list 的引用没变)
}

final 防"重新赋值"。表达"不可重新赋值"的意图。看个人偏好用不用——团队规范说了算。

实例方法的 this

public class Box {
    private int width;

    public void setWidth(int width) {
        this.width = width;        // this. 区分同名
    }
}

this = 当前对象。

链式调用(fluent API)

public class Builder {
    private String name;
    private int age;

    public Builder name(String name) {
        this.name = name;
        return this;       // 返回自己 → 链式调用
    }
    public Builder age(int age) {
        this.age = age;
        return this;
    }
}

new Builder().name("Alice").age(30);

很多 Java 库用这模式(Stream、Builder、Fluent Assertions)。

方法引用(::)

List<String> names = List.of("Alice", "Bob");

names.forEach(s -> System.out.println(s));   // lambda
names.forEach(System.out::println);          // 方法引用,等价

names.stream().map(String::toUpperCase);     // 实例方法引用
names.stream().sorted(String::compareToIgnoreCase);

详见 第 18 篇 Lambda

→ 下一篇 类、字段、构造