当前位置: 首页 > 科技观察

Java进阶:用匿名内部类实现Java同步回调

时间:2023-03-13 03:10:43 科技观察

在一个应用系统中,无论使用什么编程语言,模块之间的调用只有三种方式:同步调用、异步调用和回调。本文对回调方法进行了详细的解读,并在最后通过匿名内部类的方式实现了一个同步的回调过程。一、回调的意义在学习回调之前,我们需要了解使用回调的原因以及回调的应用场景。最好先思考两个问题:栈底通常对栈顶是不可见的,但有时候栈顶需要直接调用栈底的上层派下属去做事物。在此期间,下属可能需要通过上级获得高层的协助。中,回调方法用于处理爬取后大量的返回数据。在业务层面,这些数据被安排给调用者处理,但调用者没有足够的权限来处理这些数据。所以通过回调,很好的将业务分层执行。2、如何实现同步回调本文同步回调的业务需求如下:回调方调用调用方进行数据爬取调用方调用回调方存储数据对应代码如下:publicinterfaceHandler{voidhandle(Stringinfo);}publicclassTask{privateStringinfo;privatevoidsetInfo(Stringinfo){this.info=info;}publicvoidcall(){Crawler.getInstance().crawl(newHandler(){@Overridepublicvoidhandle(Stringinfo){setInfo(info);}});}}publicclassCrawler{privatestaticCrawlerinstance=null;publicstaticCrawlergetInstance(){if(instance==null){instance=newCrawler();}returninstance;}privateStringgetInfo(){return"theinfofromcrawler";}publicvoidcrawl(Handlerhandler){handler.handle(getInfo());}}3、遇到的问题如果我们用代码来实现上面的回调过程,不难发现这样一个问题:Task调用Crawler,Crawler调用Handler,Hanlder调用Task。很明显,这里存在一个循环,产生了循环依赖的问题,接口可以为我们提供一个很好的解决方案。4、为什么Java中有很多通过匿名内部类实现同步回调的方式?为什么要通过匿名内部类来实现回调?直接回调不好吗?先看一下直接回调的时序图:对应代码如下:getInstance().crawl(this);}@Overridepublicvoidhandle(Stringinfo){setInfo(in);}}publicclassCrawler{privatestaticCrawlerinstance=null;publicstaticCrawlergetInstance(){if(instance==null){instance=newCrawler();}returninstance;}privateStringgetInfo(){return"theinfofromcrawler";}publicvoidcrawl(Handlerhandler){handler.handle(getInfo());}}直接回调带来的最大问题就是回调接口的暴露,也就是回调接口不一定用于回调,也可以直接访问。这在业务层面的设计上是绝对不允许的,匿名内部类在执行回调等具体服务的同时,可以很好的对外界隐藏回调接口。五、总结常规类不保证接口安全:常规接口通常可以设置权限,但不能指定访问类,即要么全部可以访问,要么全部拒绝。内部类中的接口可以指定访问类。内部类保证接口安全:内部类接口通常是对外界隐藏的,那么如何将内部类暴露给指定的访问类呢?方法很简单。只需要通过外部类实例化内部类,并向指定类传递参数即可。可以使指定的类可供内部类访问。内部类的安全性与其对外部类的完全权限相结合,使其成为实现回调的首选解决方案。在JAVA8中,lambda表达式本质上是匿名内部类的语法糖。注意:匿名内部类本质上是成员内部类和局部内部类的简化表达,这里统称为内部类。