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

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

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

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

是什么

定義

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

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

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

成員:

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

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

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

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

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

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

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

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

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

實例

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

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

// ========== 步驟2:被調(diào)用方:接收回調(diào)對象,執(zhí)行核心任務(wù)后觸發(fā)回調(diào) ==========
class CallbackTaskService {
    // 核心方法:入?yún)椤富卣{(diào)接口對象」,接收調(diào)用方的邏輯
    public void doTask(MyCallback callback) {
        System.out.println("【被調(diào)用方】開始執(zhí)行耗時核心任務(wù)...");
        // 模擬核心任務(wù)執(zhí)行(如數(shù)據(jù)庫查詢、網(wǎng)絡(luò)請求)
        String taskResult = "核心任務(wù)執(zhí)行成功,返回結(jié)果";
        // 關(guān)鍵:被調(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)用方返回的結(jié)果
                System.out.println("【調(diào)用方-回調(diào)邏輯】收到被調(diào)用方結(jié)果:" + result);
            }
        };
        
        // 傳遞回調(diào)對象給被調(diào)用方
        service.doTask(callback);
        // 核心優(yōu)勢:調(diào)用方無需等待,可立即執(zhí)行自身其他邏輯
        System.out.println("【調(diào)用方】發(fā)起任務(wù)后,直接執(zhí)行自身后續(xù)邏輯,無需等待任務(wù)完成");
    }
}

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

常見應(yīng)用

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

// 回調(diào)體:Runnable是回調(diào)接口,匿名內(nèi)部類實現(xiàn)的是「回調(diào)對象」
Runnable callbackObj = new Runnable() {
    @Override
    public void run() {
        // ?? 回調(diào)方法:存放「用戶自定義的業(yè)務(wù)邏輯」(擴展邏輯)
        System.out.println("【線程回調(diào)】執(zhí)行線程內(nèi)業(yè)務(wù)邏輯");
    }
};
// 被調(diào)用方:Thread類 + JVM(核心邏輯執(zhí)行者,掌握回調(diào)觸發(fā)權(quán))
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資源 → 線程從「就緒」轉(zhuǎn)為「運行狀態(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è)務(wù)邏輯執(zhí)行完畢 → 線程進入「終止?fàn)顟B(tài)」,回調(diào)完成。

常見應(yīng)用場景

應(yīng)用領(lǐng)域具體場景核心回調(diào)接口 / 方法觸發(fā)時機
JDK 原生線程 / 線程池Runnable.run()/Callable.call()線程啟動后
JDK 原生異步回調(diào)CompletableFuture.thenAccept()異步任務(wù)完成后
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類型轉(zhuǎn)換TypeHandler.setNonNullParameter()參數(shù)設(shè)置 / 結(jié)果映射時
NettyNIO 事件ChannelHandler.channelRead()IO 事件觸發(fā)時
定時任務(wù)定時器TimerTask.run()定時時間到達時

為什么

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

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

總結(jié)

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

相關(guān)文章

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

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

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

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

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

    SpringBoot項目如何打包部署到服務(wù)器

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

    Mybatis中@Param注解的用法詳解

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

    Springboot2 配置AOP日志的方法步驟

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

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

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

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

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

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

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

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

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

    如何基于Jenkins構(gòu)建Docker鏡像

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

最新評論

邹平县| 应用必备| 聂拉木县| 工布江达县| 峨山| 太康县| 岑溪市| 浦县| 神农架林区| 托克逊县| 神池县| 中宁县| 保定市| 龙游县| 鄂托克前旗| 犍为县| 扬州市| 桦南县| 精河县| 宜君县| 九江市| 江津市| 扬州市| 武功县| 武宁县| 武威市| 黄浦区| 石河子市| 保靖县| 云林县| 毕节市| 福鼎市| 山丹县| 正镶白旗| 古蔺县| 林西县| 奉新县| 精河县| 乾安县| 长泰县| 电白县|