欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的回調(diào)機(jī)制使用方式

 更新時間:2025年08月15日 10:20:44   作者:yifanghub  
回調(diào)機(jī)制是一種編程模式,允許對象在特定事件觸發(fā)時反向調(diào)用調(diào)用方,Java中通過接口、抽象類或Lambda實現(xiàn),支持同步與異步操作,廣泛用于事件處理、異步編程等場景,具有解耦優(yōu)勢但也存在回調(diào)地獄等維護(hù)難題

什么是回調(diào)機(jī)制

回調(diào)機(jī)制(Callback)是一種常見的編程模式,它允許一個類或?qū)ο笤谔囟ㄊ录l(fā)生時通知另一個類或?qū)ο蟆:唵蝸碚f,就是"A調(diào)用B,B在執(zhí)行完成后又調(diào)用A"的過程。

回調(diào)的核心思想是反向調(diào)用,這與傳統(tǒng)的正向調(diào)用(直接調(diào)用方法)不同?;卣{(diào)機(jī)制在事件處理、異步編程、框架設(shè)計中有著廣泛應(yīng)用。

在 Java 中,回調(diào)最常見的實現(xiàn)方式是:

  1. 定義一個回調(diào)接口(Callback Interface)。
  2. 調(diào)用方持有該接口的引用,并將其傳遞給被調(diào)用方。
  3. 被調(diào)用方在合適的時機(jī)反過來調(diào)用接口方法,把結(jié)果或事件通知給調(diào)用方。

回調(diào)的基本實現(xiàn)方式

1. 基于接口的回調(diào)

這是Java中最常用的回調(diào)實現(xiàn)方式。我們定義一個回調(diào)接口,然后讓調(diào)用方實現(xiàn)這個接口,最后將實現(xiàn)類的實例傳遞給被調(diào)用方。

示例:按鈕點擊事件

// 定義回調(diào)接口
interface ClickListener {
    void onClick();
}

// 按鈕類
class Button {
    private ClickListener listener;
    
    // 設(shè)置回調(diào)監(jiān)聽器
    public void setClickListener(ClickListener listener) {
        this.listener = listener;
    }
    
    // 模擬按鈕被點擊
    public void click() {
        System.out.println("按鈕被點擊了");
        if (listener != null) {
            listener.onClick(); // 觸發(fā)回調(diào)
        }
    }
}

public class InterfaceCallbackDemo {
    public static void main(String[] args) {
        Button button = new Button();
        
        // 設(shè)置回調(diào)實現(xiàn)
        button.setClickListener(new ClickListener() {
            @Override
            public void onClick() {
                System.out.println("回調(diào)執(zhí)行:按鈕點擊事件處理");
                System.out.println("回調(diào)執(zhí)行了~");
            }
        });
        
        button.click(); // 觸發(fā)點擊事件
    }
}

說明:

  1. 定義ClickListener回調(diào)接口
  2. Button類持有接口引用,并在適當(dāng)時機(jī)調(diào)用接口方法
  3. 主程序通過匿名類實現(xiàn)接口,完成回調(diào)設(shè)置
  4. 當(dāng)click()方法被調(diào)用時,會觸發(fā)回調(diào)

執(zhí)行結(jié)果:

按鈕被點擊了
回調(diào)執(zhí)行:按鈕點擊事件處理
回調(diào)執(zhí)行了~

2. 抽象類回調(diào)

示例:任務(wù)處理器

// 定義抽象回調(diào)類
abstract class TaskHandler {
    // 抽象回調(diào)方法
    public abstract void onComplete(String result);
    
    // 可以有具體實現(xiàn)方法
    public void onStart() {
        System.out.println("任務(wù)開始處理");
    }
}

// 任務(wù)執(zhí)行類
class TaskExecutor {
    public void execute(TaskHandler handler) {
        handler.onStart();
        
        // 模擬任務(wù)執(zhí)行
        try {
            Thread.sleep(1000);
            handler.onComplete("任務(wù)完成");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

public class AbstractClassCallbackDemo {
    public static void main(String[] args) {
        TaskExecutor executor = new TaskExecutor();
        
        // 使用匿名類實現(xiàn)抽象回調(diào)類
        executor.execute(new TaskHandler() {
            @Override
            public void onComplete(String result) {
                System.out.println("回調(diào)結(jié)果: " + result);
            }
        });
    }
}

說明:

  1. 定義TaskHandler抽象類,包含抽象回調(diào)方法
  2. 抽象類可以包含具體實現(xiàn)方法(如onStart()
  3. TaskExecutor接收抽象類作為參數(shù),調(diào)用其方法
  4. 主程序通過匿名類實現(xiàn)抽象類,完成回調(diào)設(shè)置

執(zhí)行結(jié)果:

任務(wù)開始處理
回調(diào)結(jié)果: 任務(wù)完成

3. 函數(shù)式接口與Lambda表達(dá)式(Java 8+)

示例:簡單計算器

import java.util.function.BiFunction;

public class LambdaCallbackDemo {
    public static void main(String[] args) {
        // 使用BiFunction作為回調(diào)接口
        calculate(5, 3, (a, b) -> a + b);  // 加法
        calculate(5, 3, (a, b) -> a * b);  // 乘法
        
        // 更復(fù)雜的示例,數(shù)據(jù)處理回調(diào)
        processData("Hello", 
            data -> {
                String result = data + " World!";
                System.out.println("處理結(jié)果: " + result);
                return result;
            },
            error -> System.err.println("錯誤: " + error)
            );
        // 
        processData(null,
                data -> data + " World!",
                error -> System.err.println("捕獲到錯誤: " + error)
                );
    }
    
    // 計算方法,接收操作回調(diào)
    public static void calculate(int a, int b, BiFunction<Integer, Integer, Integer> operation) {
        int result = operation.apply(a, b);
        System.out.println("計算結(jié)果: " + result);
    }
    
    // 數(shù)據(jù)處理方法,接收成功和失敗回調(diào)
    public static void processData(String input, 
                                  java.util.function.Function<String, String> successHandler,
                                  java.util.function.Consumer<Exception> errorHandler) {
        try {
            if (input == null) {
                throw new IllegalArgumentException("輸入不能為null");
            }
            String result = successHandler.apply(input);
        } catch (Exception e) {
            errorHandler.accept(e);
        }
    }
}

說明:

  • 使用Java內(nèi)置的BiFunction函數(shù)式接口作為回調(diào)
  • Lambda表達(dá)式簡化了回調(diào)的實現(xiàn)
  • calculate方法接收操作邏輯作為參數(shù)
  • processData方法用了更復(fù)雜的回調(diào)場景,包含成功和錯誤處理

執(zhí)行結(jié)果:

計算結(jié)果: 8
計算結(jié)果: 15
處理結(jié)果: Hello World!
捕獲到錯誤: java.lang.IllegalArgumentException: 輸入不能為null

回調(diào)的同步與異步特性

回調(diào)本身只是一種編程模式,它既可以是同步的也可以是異步的,這取決于具體的實現(xiàn)方式

同步回調(diào)

  • 特點:回調(diào)方法在調(diào)用者方法返回前執(zhí)行
  • 執(zhí)行流程:A調(diào)用B → B執(zhí)行 → B調(diào)用A的回調(diào)方法 → B返回 → A繼續(xù)執(zhí)行

如:集合排序時傳入的Comparator

同步回調(diào)實現(xiàn)示例

// 同步回調(diào)接口
interface SyncCallback {
    void onComplete(String result);
}

class SyncProcessor {
    public void process(String input, SyncCallback callback) {
        System.out.println("處理線程: " + Thread.currentThread().getName());
        // 同步處理
        String result = input.toUpperCase();
        // 同步調(diào)用回調(diào)
        callback.onComplete(result);
    }
}

public class SyncCallbackDemo {
    public static void main(String[] args) {
        SyncProcessor processor = new SyncProcessor();
        
        System.out.println("主線程: " + Thread.currentThread().getName());
        
        processor.process("hello", result -> {
            System.out.println("回調(diào)線程: " + Thread.currentThread().getName());
            System.out.println("同步結(jié)果: " + result);
        });
        
        System.out.println("主線程繼續(xù)執(zhí)行...");
    }
}

執(zhí)行結(jié)果

主線程: main
處理線程: main
回調(diào)線程: main
同步結(jié)果: HELLO
主線程繼續(xù)執(zhí)行...

異步回調(diào)

  • 特點:回調(diào)方法在另一個線程執(zhí)行
  • 執(zhí)行流程:A調(diào)用B → B立即返回 → B啟動新線程執(zhí)行任務(wù) → 任務(wù)完成后在新線程調(diào)用A的回調(diào)方法

如:網(wǎng)絡(luò)請求的響應(yīng)回調(diào)

異步回調(diào)實現(xiàn)示例

// 異步回調(diào)接口
interface AsyncCallback {
    void onComplete(String result);
}

class AsyncProcessor {
    public void process(String input, AsyncCallback callback) {
        System.out.println("調(diào)用線程: " + Thread.currentThread().getName());
        
        // 啟動新線程異步處理
        new Thread(() -> {
            System.out.println("處理線程: " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000); // 模擬耗時操作
                String result = input.toUpperCase();
                callback.onComplete(result);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
}

public class AsyncCallbackDemo {
    public static void main(String[] args) {
        AsyncProcessor processor = new AsyncProcessor();
        
        System.out.println("主線程: " + Thread.currentThread().getName());
        
        processor.process("hello", result -> {
            System.out.println("回調(diào)線程: " + Thread.currentThread().getName());
            System.out.println("異步結(jié)果: " + result);
        });
        
        System.out.println("主線程繼續(xù)執(zhí)行...");
        
        // 防止主線程過早退出
        try { Thread.sleep(1500); } catch (InterruptedException e) {}
    }
}

執(zhí)行結(jié)果

主線程: main
調(diào)用線程: main
主線程繼續(xù)執(zhí)行...
處理線程: Thread-0
回調(diào)線程: Thread-0
異步結(jié)果: HELLO

回調(diào)的一些應(yīng)用實例

場景回調(diào)接口說明
JDBC 驅(qū)動RowCallbackHandlerSpring JdbcTemplate 每查出一行就回調(diào)一次
GUI 事件ActionListenerSwing/AWT 點擊按鈕觸發(fā)
Servlet 3.0AsyncListener異步 Servlet 完成/超時/錯誤時回調(diào)
NettyChannelFutureListenerIO 操作完成后回調(diào)
Spring 生命周期InitializingBean, DisposableBean容器啟動/銷毀時回調(diào)
GuavaListenableFuture + Futures.addCallback早于 CompletableFuture 的回調(diào)方案

小結(jié)

回調(diào)的優(yōu)缺點

優(yōu)點:

  • 解耦:回調(diào)可以將調(diào)用方和被調(diào)用方解耦
  • 異步處理:非常適合處理異步操作和事件驅(qū)動編程
  • 靈活性:可以在運行時決定具體執(zhí)行什么操作

缺點

  • 回調(diào)地獄:多層嵌套回調(diào)會導(dǎo)致代碼難以閱讀和維護(hù)
  • 異常處理復(fù)雜:在異步回調(diào)中處理異常比同步代碼更困難
  • 調(diào)試?yán)щy:回調(diào)的執(zhí)行流程不如線性代碼直觀

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • org.apache.ibatis.annotations不存在的問題

    org.apache.ibatis.annotations不存在的問題

    這篇文章主要介紹了org.apache.ibatis.annotations不存在的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • logback的使用和logback.xml詳解(小結(jié))

    logback的使用和logback.xml詳解(小結(jié))

    Logback是由log4j創(chuàng)始人設(shè)計的另一個開源日志組件,這篇文章主要介紹了logback的使用和logback.xml詳解(小結(jié)),非常具有實用價值,需要的朋友可以參考下
    2018-11-11
  • 解決spring data redis的那些坑

    解決spring data redis的那些坑

    這篇文章主要介紹了spring data redis的那些坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java Set接口及常用實現(xiàn)類總結(jié)

    Java Set接口及常用實現(xiàn)類總結(jié)

    Collection的另一個子接口就是Set,他并沒有我們List常用,并且自身也沒有一些額外的方法,全是繼承自Collection中的,因此我們還是簡單總結(jié)一下,包括他的常用實現(xiàn)類HashSet、LinkedHashSet、TreeSet的總結(jié)
    2023-01-01
  • Java并發(fā)編程數(shù)據(jù)庫與緩存數(shù)據(jù)一致性方案解析

    Java并發(fā)編程數(shù)據(jù)庫與緩存數(shù)據(jù)一致性方案解析

    這篇文章主要為大家介紹了Java并發(fā)編程中數(shù)據(jù)庫與緩存數(shù)據(jù)一致性解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • 詳解JAVA常用的時間操作【實用】

    詳解JAVA常用的時間操作【實用】

    本文主要介紹了JAVA一些常用的時間操作,很實用,相信大家在開發(fā)項目時會用到,下面就跟小編一起來看下吧
    2016-12-12
  • Java中的線程死鎖是什么?如何避免?

    Java中的線程死鎖是什么?如何避免?

    這篇文章主要介紹了Java中線程死鎖的相關(guān)資料,以及避免死鎖的方法,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-09-09
  • Java List移除相應(yīng)元素的超簡潔寫法分享

    Java List移除相應(yīng)元素的超簡潔寫法分享

    這篇文章主要介紹了Java List移除相應(yīng)元素的超簡潔寫法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • springboot Controller直接返回String類型帶來的亂碼問題及解決

    springboot Controller直接返回String類型帶來的亂碼問題及解決

    文章介紹了在Spring Boot中,當(dāng)Controller直接返回String類型時可能出現(xiàn)的亂碼問題,并提供了解決辦法,通過在`application.yaml`中設(shè)置請求和響應(yīng)的編碼格式,并在自定義配置類中進(jìn)行配置,可以有效解決這一問題
    2024-11-11
  • spring如何使用xml裝配bean

    spring如何使用xml裝配bean

    這篇文章主要介紹了spring如何使用xml裝配bean,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11

最新評論