定义
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) {
...
}
抛受检异常(继承 Exception 非 RuntimeException)的方法必须 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。
→ 下一篇 类、字段、构造