回調 是一種「雙向調用」約定:A 類持有 B 類的引用並呼叫其方法;B 類在特定時機反向呼叫 A 類實現的介面方法。本質上是好萊塢原則:「不要調用我們,我們會調用你」。
// 1. 定義回調介面
public interface Callback {
void before();
void after();
}
// 2. 被調用方:持有介面引用,在關鍵節點觸發
public class TaskExecutor {
private final Callback callback;
public TaskExecutor(Callback callback) {
this.callback = callback;
}
public void execute() {
callback.before(); // 前置通知
System.out.println("hello chenyu"); // 核心業務
callback.after(); // 後置通知
}
}
// 3. 調用方:實現介面並傳遞 this
public class Client implements Callback {
private final TaskExecutor executor = new TaskExecutor(this);
@Override public void before() { System.out.println("hello before"); }
@Override public void after() { System.out.println("hello after"); }
public void start() { executor.execute(); }
public static void main(String[] args) {
new Client().start();
}
}
hello before hello chenyu hello after
// 無需顯式實現類,直接用 Lambda
TaskExecutor executor = new TaskExecutor(() -> System.out.println("前"),
() -> System.out.println("後"));
executor.execute();
配合 @FunctionalInterface 註解可強制介面為單一抽象方法,進一步簡化。
| 誤區 | 後果 | 正確做法 |
|---|---|---|
| 回調方法拋出未檢查異常 | 導致執行方中斷,資源洩漏 | 回調內部捕獲異常或定義 checked exception 讓執行方處理 |
| 回調持有外部強引用 | 記憶體洩漏(特別是 Android Activity) | 使用 WeakReference 或生命週期綁定 |
| 同步回調執行耗時操作 | 阻塞調用線程,降低吞吐 | 改為異步回調(CompletableFuture、RxJava、协程) |