最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文徹底搞懂Java中的回調(diào)函數(shù)

 更新時間:2026年01月20日 10:08:42   作者:馬猴燒酒.  
回調(diào)是一種常見的編程模式,允許一個函數(shù)在特定事件或任務完成后,調(diào)用另一個預先定義的函數(shù),這篇文章主要介紹了Java中回調(diào)函數(shù)的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

在學習代理設計模式中提到了“回調(diào)”這個東東,一下子把我打蒙了。于是決心花點小時間徹底理解java里的回調(diào)是什么。

是什么

定義

回調(diào)(Callback)是 Java 中最基礎、最核心的編程設計思想,本質(zhì)是「方法作為參數(shù)傳遞 + 控制權反轉」的實現(xiàn)。回調(diào)邏輯的執(zhí)行時機,由被調(diào)用方?jīng)Q定,而非調(diào)用方(控制權反轉)

回調(diào) = 調(diào)用方把「自己的邏輯(方法)」交給被調(diào)用方 → 被調(diào)用方在「指定時機」主動執(zhí)行該邏輯。

好比點外賣時(場景)我把我的電話號碼(對象)交給店鋪(被調(diào)用者),店鋪會在我的外賣送到時(指定時機)給我打電話(對象可以調(diào)用的方法)。

成員:

心成員 1:「調(diào)用方(Caller)」

? 核心職責:定義回調(diào)邏輯(或持有已有類的回調(diào)方法) + 將回調(diào)載體(接口對象 / 普通類對象)傳遞給被調(diào)用方;

? 核心特征:主動發(fā)起交互,把自己的邏輯交付出去,不控制回調(diào)執(zhí)行時機。

 核心成員 2:「被調(diào)用方(Callee)」

? 核心職責:接收回調(diào)載體 + 執(zhí)行自身核心業(yè)務 + 在指定時機主動調(diào)用回調(diào)載體中的方法;

? 核心特征:擁有「回調(diào)觸發(fā)權」,決定回調(diào)邏輯什么時候執(zhí)行,是回調(diào)的主導方。

核心成員 3:「回調(diào)體(Callback Body)」

? 核心定義:封裝了回調(diào)邏輯的載體(可以是「接口實現(xiàn)類對象」、也可以是「已有方法的普通類對象」),是調(diào)用方與被調(diào)用方的「通信橋梁」;

? 核心特征:內(nèi)部包含具體的「回調(diào)方法」,供被調(diào)用方主動觸發(fā)。

實例

同步回調(diào)(對應的異步會回調(diào)就是在被調(diào)用方內(nèi)部開個獨立線程)

// ========== 步驟1:定義回調(diào)接口(約定回調(diào)方法規(guī)范,核心) ==========
interface MyCallback {
    // 回調(diào)方法:被調(diào)用方在「任務完成后」主動調(diào)用
    void onTaskFinish(String result);
}

// ========== 步驟2:被調(diào)用方:接收回調(diào)對象,執(zhí)行核心任務后觸發(fā)回調(diào) ==========
class CallbackTaskService {
    // 核心方法:入?yún)椤富卣{(diào)接口對象」,接收調(diào)用方的邏輯
    public void doTask(MyCallback callback) {
        System.out.println("【被調(diào)用方】開始執(zhí)行耗時核心任務...");
        // 模擬核心任務執(zhí)行(如數(shù)據(jù)庫查詢、網(wǎng)絡請求)
        String taskResult = "核心任務執(zhí)行成功,返回結果";
        // 關鍵:被調(diào)用方主動觸發(fā)回調(diào)(時機由被調(diào)用方?jīng)Q定)
        callback.onTaskFinish(taskResult);
    }
}

// ========== 步驟3:調(diào)用方:實現(xiàn)回調(diào)接口,傳遞回調(diào)對象 ==========
public class CallbackCallDemo {
    public static void main(String[] args) {
        CallbackTaskService service = new CallbackTaskService();
        
        // 調(diào)用方通過「匿名內(nèi)部類」實現(xiàn)回調(diào)接口
        MyCallback callback = new MyCallback() {
            @Override
            public void onTaskFinish(String result) {
                // 調(diào)用方自定義的回調(diào)邏輯:處理被調(diào)用方返回的結果
                System.out.println("【調(diào)用方-回調(diào)邏輯】收到被調(diào)用方結果:" + result);
            }
        };
        
        // 傳遞回調(diào)對象給被調(diào)用方
        service.doTask(callback);
        // 核心優(yōu)勢:調(diào)用方無需等待,可立即執(zhí)行自身其他邏輯
        System.out.println("【調(diào)用方】發(fā)起任務后,直接執(zhí)行自身后續(xù)邏輯,無需等待任務完成");
    }
}

注意,這里不是必須得有個接口什么的,這不是一種固定的代碼寫法而是一種設計模式。只是使用接口可以實現(xiàn)強解耦,統(tǒng)一規(guī)范,是最佳實踐。在實例代碼的基礎上還可以用lambda簡化等等。

常見應用

像代理模式中就有用到,不過里面層層包裝很難看清怎么用的,這里只講講線程 / 線程池回調(diào)。

// 回調(diào)體:Runnable是回調(diào)接口,匿名內(nèi)部類實現(xiàn)的是「回調(diào)對象」
Runnable callbackObj = new Runnable() {
    @Override
    public void run() {
        // ?? 回調(diào)方法:存放「用戶自定義的業(yè)務邏輯」(擴展邏輯)
        System.out.println("【線程回調(diào)】執(zhí)行線程內(nèi)業(yè)務邏輯");
    }
};
// 被調(diào)用方:Thread類 + JVM(核心邏輯執(zhí)行者,掌握回調(diào)觸發(fā)權)
Thread thread = new Thread(callbackObj);
// 調(diào)用方:我們的主線程代碼(傳遞回調(diào)體、發(fā)起調(diào)用,不控制觸發(fā)時機)
thread.start(); 

執(zhí)行鏈路

1. 主線程調(diào)用 thread.start() → 向JVM發(fā)起「線程啟動請求」,線程進入「就緒狀態(tài)」;

2. JVM線程調(diào)度器分配CPU資源 → 線程從「就緒」轉為「運行狀態(tài)」;

3. JVM底層主動調(diào)用 Thread類中的run()方法;

4. Thread類的run()方法內(nèi)部,會調(diào)用「傳入的Runnable對象」的run()方法;

5.  最終觸發(fā):我們自定義的回調(diào)邏輯(Runnable匿名內(nèi)部類的run())執(zhí)行;

6. 業(yè)務邏輯執(zhí)行完畢 → 線程進入「終止狀態(tài)」,回調(diào)完成。

常見應用場景

應用領域具體場景核心回調(diào)接口 / 方法觸發(fā)時機
JDK 原生線程 / 線程池Runnable.run()/Callable.call()線程啟動后
JDK 原生異步回調(diào)CompletableFuture.thenAccept()異步任務完成后
JDK 原生集合遍歷Collection.forEach()遍歷每個元素時
Spring 生態(tài)Bean 生命周期InitializingBean.afterPropertiesSet()Bean 初始化完成后
Spring 生態(tài)事件監(jiān)聽ApplicationListener.onApplicationEvent()發(fā)布事件時
Spring 生態(tài)MVC 攔截器HandlerInterceptor.preHandle()請求處理前后
動態(tài)代理CGLIB/JDK 代理MethodInterceptor.intercept()/InvocationHandler.invoke()調(diào)用代理方法時
MyBatis類型轉換TypeHandler.setNonNullParameter()參數(shù)設置 / 結果映射時
NettyNIO 事件ChannelHandler.channelRead()IO 事件觸發(fā)時
定時任務定時器TimerTask.run()定時時間到達時

為什么

其實跟大多數(shù)設計模式一樣,還是「傳遞邏輯、移交控制、分離職責」這些優(yōu)點,幫助我們寫出邏輯性更強更簡約的代碼。

不過這里的什么解決代碼緊耦合,設計模式里的裝飾器模式,觀察者模式等等都能做到。代碼量太低的我就很難理解里面的精妙之處,特別之處了,這里更多的是記住“這種場景”來選擇使用。

總結

到此這篇關于Java中回調(diào)函數(shù)的文章就介紹到這了,更多相關Java回調(diào)函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java后臺接收app上傳的圖片的示例代碼

    java后臺接收app上傳的圖片的示例代碼

    本篇文章主要介紹了java后臺接受app上傳的圖片的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • springboot解決前后端分離時的跨域問題

    springboot解決前后端分離時的跨域問題

    這篇文章主要介紹了springboot如何解決前后端分離時的跨域問題,幫助大家更好的理解和學習使用springboot,感興趣的朋友可以了解下
    2021-04-04
  • SpringBoot項目如何打包部署到服務器

    SpringBoot項目如何打包部署到服務器

    這篇文章主要介紹了SpringBoot項目如何打包部署到服務器問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Mybatis中@Param注解的用法詳解

    Mybatis中@Param注解的用法詳解

    @Param注解的作用是給參數(shù)命名,參數(shù)命名后就能根據(jù)名字得到參數(shù)值,正確的將參數(shù)傳入sql語句中,下面這篇文章主要給大家介紹了關于Mybatis中@Param注解用法的相關資料,需要的朋友可以參考下
    2022-07-07
  • Springboot2 配置AOP日志的方法步驟

    Springboot2 配置AOP日志的方法步驟

    這篇文章主要介紹了Springboot2 配置AOP日志的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • 使用IntelliJ IDEA調(diào)式Stream流的方法步驟

    使用IntelliJ IDEA調(diào)式Stream流的方法步驟

    本文主要介紹了使用IntelliJ IDEA調(diào)式Stream流的方法步驟,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Java線程中賣火車票問題的深入講解

    Java線程中賣火車票問題的深入講解

    這篇文章主要給大家介紹了關于Java線程中賣火車票問題的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • Spring Bean初始化及@PostConstruc執(zhí)行順序示例詳解

    Spring Bean初始化及@PostConstruc執(zhí)行順序示例詳解

    本文給大家介紹Spring Bean初始化及@PostConstruc執(zhí)行順序,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-07-07
  • 關于Springboot | @RequestBody 接收到的參數(shù)對象屬性為空的問題

    關于Springboot | @RequestBody 接收到的參數(shù)對象屬性為空的問題

    這篇文章主要介紹了關于Springboot | @RequestBody 接收到的參數(shù)對象屬性為空的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 如何基于Jenkins構建Docker鏡像

    如何基于Jenkins構建Docker鏡像

    這篇文章主要介紹了基于Jenkins構建Docker鏡像,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11

最新評論

西藏| 南昌县| 汶上县| 定襄县| 南开区| 阿尔山市| 察隅县| 手游| 应用必备| 女性| 长宁区| 新龙县| 深水埗区| 鸡东县| 根河市| 瑞昌市| 九江市| 长宁区| 延边| 津南区| 岳池县| 九寨沟县| 汨罗市| 奉贤区| 庆阳市| 泾源县| 措美县| 晋宁县| 苍梧县| 吉林市| 文昌市| 上林县| 蕲春县| 安吉县| 都江堰市| 阿荣旗| 东方市| 武川县| 新田县| 灵璧县| 陕西省|