日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Java回調的四種寫法:反射+直接調用+接口調用+Lambda表達式

1. 引言

在計算機程序設計中,回調函數,簡稱回調(Callback),是指通過函數參數傳遞到其他代碼的,某一塊可執行代碼的引用。這一設計允許了底層代碼調用在高層定義的子程序。

以上是維基百科對“回調函數”的定義。對于回調,不同的語言有不同的回調形式,例如:

  • C、C++ 允許將函數指針作為參數傳遞;
  • JAVAScript、Python 允許將函數名作為參數傳遞。

本文將介紹 Java 實現回調的四種寫法:

  • 反射;
  • 直接調用;
  • 接口調用;
  • Lambda表達式。

在開始之前,先介紹下本文代碼示例的背景,在 main 函數中,我們異步發送一個請求,并且指定處理響應的回調函數,接著 main 函數去做其他事,而當響應到達后,執行回調函數。

2. 反射

Java 的反射機制允許我們獲取類的信息,其中包括類的方法。我們將以 Method 類型去獲取回調函數,然后傳遞給請求函數。示例如下:

Request 類中的 send 方法有兩個參數 clazz、method,分別是Class 類型和 Method 類型,這里的 method 參數就是待傳入的回調函數,而為了通過 invoke 方法進行反射調用,還需要一個實例,所以將回調函數所在的類的 Class 對象作為參數傳遞進來,通過 newInstance 構造一個對象,將順利通過 invoke 反射調用。

public class Request{
    public void send(Class clazz, Method method) throws Exception {
        // 模擬等待響應
        Thread.sleep(3000);
        System.out.println("[Request]:收到響應");
        method.invoke(clazz.newInstance());
    }
}

CallBack 類很簡單,只有一個 processResponse 方法,用于當作回調函數,處理響應。

public class CallBack {
    public void processResponse() {
        System.out.println("[CallBack]:處理響應");
    }
}

我們在 main 方法中,新開了一個線程去發送請求,并且把需要的 CallBack.class 和 processResponse 方法傳遞進去。

public class Main {
    public static void main(String[] args) throws Exception {
        Request request = new Request();
        System.out.println("[Main]:我開個線程去異步發請求");
        new Thread(() -> {
            try {
                request.send(CallBack.class, CallBack.class.getMethod("processResponse"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        System.out.println("[Main]:請求發完了,我去干點別的");
        Thread.sleep(100000);
    }
}
/** Output:
[Main]:我開個線程去異步發請求
[Main]:請求發完了,我去干點別的
[Request]:收到響應
[CallBack]:處理響應
*/

這種寫法需要傳遞的參數十分繁瑣。下面介紹一種簡單的寫法,直接調用。

3. 直接調用

我們來改寫下 send 方法的參數,改為一個 CallBack 類型參數。如下:

在 send 方法中我們不使用反射,改為直接通過對象來調用方法。

public class Request{
    public void send(CallBack callBack) throws Exception {
        // 模擬等待響應
        Thread.sleep(3000);
        System.out.println("[Request]:收到響應");
        callBack.processResponse();
    }
}

main 函數中,我們 new 了一個 CallBack 對象作為參數傳遞給 send 方法。

public class Main {
    public static void main(String[] args) throws Exception {
        Request request = new Request();
        System.out.println("[Main]:我開個線程去異步發請求");
        CallBack callBack = new CallBack();
        new Thread(() -> {
            try {
                request.send(callBack);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        System.out.println("[Main]:請求發完了,我去干點別的");
        Thread.sleep(100000);
    }
}

這種實現方式十分簡單,但是存在的問題是不符合修改封閉原則。也就是說當我們想要換一種“處理響應”的方法時,將必須去修改 CallBack 類的 processRequest()方法。而如果將 CallBack 類改為接口,我們就可以僅更換 CallBack 的實現了。下面請看接口調用的寫法。

4. 接口調用

首先將 CallBack 類改為接口。

public interface CallBack {
    public void processResponse();
}
復制代碼

再新增一個 CallBack 接口的實現類 CallBackImpl。

public class CallBackImpl implements CallBack {
    @Override
    public void processResponse() {
        System.out.println("[CallBack]:處理響應");
    }
}

Request 類不變。Main 類中的 main 方法將實例化一個 CallBackImpl,然后通過 CallBack 接口傳遞進去。

public class Main {
    public static void main(String[] args) throws Exception {
        Request request = new Request();
        System.out.println("[Main]:我開個線程去異步發請求");
        CallBack callBack = new CallBackImpl();
        new Thread(() -> {
            try {
                request.send(callBack);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        System.out.println("[Main]:請求發完了,我去干點別的");
        Thread.sleep(100000);
    }
}

5. Lambda表達式

上述方法已經介紹的差不多了,最后我們再介紹一種更加簡潔的寫法,通過使用 Lamda 表達式,將不用新增一個 CallBack 接口的實現類。下面請看改寫的 main 方法:

public class Main {
    public static void main(String[] args) throws Exception {
        Request request = new Request();
        System.out.println("[Main]:我開個線程去異步發請求");
        new Thread(() -> {
            try {
                request.send(()-> System.out.println("[CallBack]:處理響應"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        System.out.println("[Main]:請求發完了,我去干點別的");
        Thread.sleep(100000);
    }
}

我們既不用去新增實現類,也不用去實例化,只需要傳遞 Lambda 表達式就可以完成回調了


作者:草捏子
原文鏈接:https://juejin.im/post/5e4948c7e51d4526c70fa2ec

分享到:
標簽:回調 Java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定