首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 回調機制(Callback)全景圖解:從幼兒園故事到生產級設計模式

     編輯:Java 程式設計入門

引言:為什麼要理解回調?

回調機制是 Java 異步編程、事件驅動、框架擴展的基石。許多初學者被「誰調用誰」、「接口怎麼定義」繞暈。本文通過一個層層遞進的幼兒園故事,將抽象概念具象化,最後落地到標準的「接口 + 內部類」工程實現。

第一章:獨自完成——無回調的同步調用

場景:小明自己心算「1+1=2」並填空。

public class Student {
    private String name;
    public Student(String name) { this.name = name; }
    
    private int calcAdd(int a, int b) { return a + b; } // 內部實現
    
    public void fillBlank(int a, int b) {
        int result = calcAdd(a, b); // 同步調用,阻塞等待
        System.out.println(name + "心算: " + a + " + " + b + " = " + result);
    }
}

特點:調用者(Student)自包含邏輯,執行路徑單一,無異步、無解耦。

第二章:工具輔助——委託調用,仍非回調

場景:題目變難「168+291」,小明借用計算器對象完成計算。

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

public class Student {
    // ...
    private int useCalculator(int a, int b) {
        return new Calculator().add(a, b); // 直接依賴具體類
    }
    public void fillBlank(int a, int b) {
        int result = useCalculator(a, b);
        System.out.println(name + "用計算器: " + a + " + " + b + " = " + result);
    }
}

進化:計算邏輯分離,但 Student 仍強依賴 Calculator 具體類,且調用同步阻塞。

第三章:關鍵轉折——真正的回調誕生

場景:超難題「26549+16487」,小明把題目和「填空位置」(自身引用)交給小紅,自己去玩。小紅算完後,「回調」小明的填空方法。

3.1 核心代碼結構

// 1. 超級計算器(服務提供方)
public class SuperCalculator {
    public void add(int a, int b, Student xiaoming) {
        int result = a + b;
        xiaoming.fillBlank(a, b, result); // 回調調用
    }
}

// 2. 學生(調用方/被回調方)
public class Student {
    // ...
    public void callHelp(int a, int b) {
        new SuperCalculator().add(a, b, this); // 傳遞自身引用
    }
    public void fillBlank(int a, int b, int result) { // 回調方法
        System.out.println(name + "求助小紅: " + a + " + " + b + " = " + result);
    }
}

3.2 執行流程圖解

  1. Student.callHelp() 主動調用 SuperCalculator.add()
  2. 傳遞參數 a、b 和 this(自身引用)
  3. SuperCalculator 內部計算完成
  4. SuperCalculator 反向調用 Student.fillBlank() —— 這就是回調

第四章:工程化升級——接口解耦與多客戶端支持

問題:小紅想同時服務小明(學生)和婆婆(攤販),不能強依賴 Student 類。

4.1 定義統一契約接口

public interface DoJob {
    void fillBlank(int a, int b, int result); // 統一回調方法
}

4.2 服務端依賴接口而非實現

public class SuperCalculator {
    public void add(int a, int b, DoJob customer) {
        int result = a + b;
        customer.fillBlank(a, b, result); // 面向接口編程
    }
}

4.3 客戶端用內部類實現接口(隱藏內部細節)

// 學生端
public class Student {
    private String name;
    public Student(String name) { this.name = name; }
    
    private class DoHomeWork implements DoJob {
        @Override
        public void fillBlank(int a, int b, int result) {
            System.out.println(name + "求助小紅計算: " + a + " + " + b + " = " + result);
        }
    }
    public void callHelp(int a, int b) {
        new SuperCalculator().add(a, b, new DoHomeWork());
    }
}

// 攤販端
public class Seller {
    private String name;
    // 同理實現 DoJob,邏輯不同(顯示「元」)
}

第五章:本質總結與生產級應用

階段關鍵特徵對應技術場景
同步直調調用者包含實現工具類、Utils
委託調用依賴具體協作類Service 層調用 Repository
回調模式雙向依賴:調用者傳自身引用,被調用者反向調用事件監聽、異步回調、模板方法、攔截器
接口回調面向接口解耦,支持多實現Listener、Callback 接口、Spring AOP

核心三要素

  1. 接口契約:定義回調方法簽名(如 DoJob.fillBlank)
  2. 引用傳遞:調用者將 this 或實現類實例傳給服務方
  3. 反向調用:服務方在適當時機調用接口方法

經典應用場景

  • java.util.Comparator:排序時的回調比較邏輯
  • Servlet Filter 鏈:doFilter(request, response, chain) 中的 chain.doFilter() 即回調
  • Spring JdbcTemplate:query(sql, new RowCallbackHandler() {...})
  • Netty/Vert.x 異步網絡框架的 ChannelFutureListener

理解回調,關鍵在於「好萊塢原則」:Don't call us, we'll call you. 服務提供方控制流程,調用者只需提供「完成後該做什麼」的邏輯封裝。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved