如何用匿名內(nèi)部類實(shí)現(xiàn) Java 同步回調(diào)
在一個(gè)應(yīng)用系統(tǒng)中,不論使用何種編程語(yǔ)言,模塊之間要進(jìn)行調(diào)用,僅存在三種方式:同步調(diào)用、異步調(diào)用、回調(diào)。本文就其中回調(diào)方式進(jìn)行詳細(xì)解讀,并通過匿名內(nèi)部類的手段,在最后實(shí)現(xiàn)一個(gè)同步回調(diào)的過程。
一、回調(diào)的意義
在學(xué)習(xí)回調(diào)之前,我們需要知道使用回調(diào)的原因,和回調(diào)的應(yīng)用場(chǎng)景。
不如先思考兩個(gè)問題:
- 棧底對(duì)棧頂通常是不可見的,但是棧頂有時(shí)需要直接調(diào)用棧底
- 上級(jí)派下級(jí)做事,在此期間,下級(jí)可能需要通過上級(jí)獲取高權(quán)限的協(xié)助
而在本例中,回調(diào)方式被用來(lái)處理爬取后的大量返回?cái)?shù)據(jù)。在業(yè)務(wù)層面,這些數(shù)據(jù)被安排在調(diào)用方進(jìn)行處理,但是調(diào)用方卻沒有處理這些數(shù)據(jù)的足夠權(quán)限。于是,通過回調(diào),業(yè)務(wù)被很好的分層并且執(zhí)行。
二、如何實(shí)現(xiàn)同步回調(diào)
本文對(duì)同步回調(diào)的業(yè)務(wù)需求如下:
- 回調(diào)方調(diào)用調(diào)用方進(jìn)行數(shù)據(jù)爬取
- 調(diào)用方調(diào)用回調(diào)方進(jìn)行數(shù)據(jù)存儲(chǔ)
- 調(diào)用方調(diào)用回調(diào)方進(jìn)行日志記錄
根據(jù)需求可以得到回調(diào)過程的時(shí)序圖:

相應(yīng)代碼如下:
public interface Handler {
void handle(String info);
}
public class Task {
private String info;
private void setInfo(String info) {
this.info = info;
}
public void call() {
Crawler.getInstance().crawl(new Handler() {
@Override
public void handle(String info) {
setInfo(info);
}
});
}
}
public class Crawler {
private static Crawler instance = null;
public static Crawler getInstance() {
if (instance == null) {
instance = new Crawler();
}
return instance;
}
private String getInfo() {
return "the info from crawler";
}
public void crawl(Handler handler) {
handler.handle(getInfo());
}
}
三、遇到的問題
如果我們使用代碼來(lái)實(shí)現(xiàn)上述回調(diào)過程,不難會(huì)發(fā)現(xiàn)這樣一個(gè)問題:Task調(diào)用Crawler,Crawler調(diào)用Handler,Hanlder調(diào)用Task。很明顯,此處存在一個(gè)環(huán),產(chǎn)生了循環(huán)依賴的問題,而接口可以為我們提供良好的解決方案。

四、為什么通過匿名內(nèi)部類的方式
用 Java 實(shí)現(xiàn)同步回調(diào)有許多方式,為什么我們要通過匿名內(nèi)部類的方式來(lái)實(shí)現(xiàn)回調(diào),直接回調(diào)不香嗎?
不妨先看看直接回調(diào)的順序圖:

相應(yīng)代碼如下:
public interface Handler {
void handle(String info);
}
public class Task implements Handler{
private String info;
private void setInfo(String info) {
this.info = info;
}
public void call() {
Crawler.getInstance().crawl(this);
}
@Override
public void handle(String info) {
setInfo(info);
}
}
public class Crawler {
private static Crawler instance = null;
public static Crawler getInstance() {
if (instance == null) {
instance = new Crawler();
}
return instance;
}
private String getInfo() {
return "the info from crawler";
}
public void crawl(Handler handler) {
handler.handle(getInfo());
}
}
直接回調(diào)帶來(lái)的最大問題便是回調(diào)接口的暴露,也就是說(shuō)回調(diào)接口不一定用于回調(diào),也可以用于直接訪問。這在業(yè)務(wù)層面的設(shè)計(jì)上是絕對(duì)不允許的,而匿名內(nèi)部類在執(zhí)行回調(diào)等特定業(yè)務(wù)的同時(shí),可以很好的對(duì)外隱藏用于回調(diào)的接口。
五、總結(jié)
常規(guī)類通常無(wú)法對(duì)回調(diào)等特定接口作出限定,要么都可以訪問,要么都拒絕訪問。而內(nèi)部類通過犧牲自身的被訪問權(quán)限,提升了自身訪問外部類的能力,這使得其成為實(shí)現(xiàn)回調(diào)的首選方案。在JAVA8中,lambda表達(dá)式本質(zhì)上就是匿名內(nèi)部類的語(yǔ)法糖。
注:匿名內(nèi)部類本質(zhì)上是成員內(nèi)部類、局部?jī)?nèi)部類的簡(jiǎn)化寫法,這里將其統(tǒng)稱為內(nèi)部類。
參考鏈接
[2] http://www.fzitv.net/article/192275.htm
[3] http://www.fzitv.net/article/105016.htm
以上就是如何用匿名內(nèi)部類實(shí)現(xiàn) Java 同步回調(diào)的詳細(xì)內(nèi)容,更多關(guān)于Java 同步回調(diào)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot數(shù)據(jù)庫(kù)初始化datasource配置方式
這篇文章主要為大家介紹了SpringBoot數(shù)據(jù)庫(kù)初始化datasource配置方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
SpringBoot+WebSocket實(shí)現(xiàn)即時(shí)通訊的方法詳解
這篇文章主要為大家詳細(xì)介紹了如何利用SpringBoot+WebSocket實(shí)現(xiàn)即時(shí)通訊功能,文中示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以參考一下2022-05-05
java實(shí)現(xiàn)簡(jiǎn)單中國(guó)象棋
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單中國(guó)象棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Java并發(fā)包工具類CountDownLatch的應(yīng)用詳解
CountDownLatch是Java并發(fā)包中非常實(shí)用的一個(gè)工具類,它可以幫助我們實(shí)現(xiàn)線程之間的同步和協(xié)作。本文主要介紹了CountDownLatch的應(yīng)用場(chǎng)景及最佳實(shí)踐,希望對(duì)大家有所幫助2023-04-04
Java實(shí)戰(zhàn)之醫(yī)院管理系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了如何利用Java實(shí)現(xiàn)醫(yī)院管理系統(tǒng),文中用到的技術(shù)有:SpringBoot、Layui、Freemaker等,感興趣的同學(xué)可以了解一下2022-04-04
Java實(shí)現(xiàn)擲骰子控制臺(tái)和窗體兩種方法
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)擲骰子控制臺(tái)和窗體兩種方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08

