回调(callback)

回调(callback)1 什么是回调软件模块之间总是存在一定的接口 从调用方式上 可以把他们分为三类 同步调用 回调和异步调用 同步调用是一种阻塞式调用 调用方要等待对方执行完毕才返回 它是一种单向调用 回调是一种双向调用模式 也就是说 被调用方在接口被调用时也会调用对方的接口 异步调用是一种类似消息或事件的机制 不过它的调用方向刚好相反 接口的服务在收到某种讯息或发生某种事件时 会主动通知客户方 即调用客户方

http://www.importnew.com/19301.html

回调的核心就是回调方将本身即this传递给调用方,这样调用方就可以在调用完毕之后告诉回调方它想要知道的信息。

1、什么是回调

软件模块之间总是存在一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。

(1)同步调用:

在这里插入图片描述
同步调用是最基本并且最简单的一种调用方式,类A的方法a()调用类B的方法b(),一直等待b()方法执行完毕,a()方法再继续往下走。这种调用方式适用于方法b()执行时间不长的情况,因为b()方法执行时间一长或者直接阻塞的话,a()方法的余下代码是无法执行下去的,这样会造成整个流程的阻塞。

(2)异步调用:

在这里插入图片描述
是一种类似消息或事件的机制,是为了解决同步调用可能出现阻塞,导致整个流程卡住而产生的一种调用方式。类A的方法a()通过新起线程的方式调用类B的方法b(),代码接着直接往下执行,这样无论方法b()执行时间多久,都不会阻塞方法a()的执行。但是这种方式,由于方法a()不等待方法b()执行完成,在方法a()需要方法b()执行结果的情况下(视具体业务而定,有些业务比如启动异步线程发个微信通知、刷新一个缓存这种就没有必要),必须通过一定的方法对方法b()的执行结果进行监听。在Java中,可以使用Future+Callable的方式做到这一点。

(3)回调:

在这里插入图片描述

最后是回调,回调的思想是:

  • 类A的a()方法调用了类B的b()方法
  • 类B的b方法执行完毕主动调用类A的callback()方法

这样一种调用方式组成了上图,也就是一种双向的调用方式

回调函数是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。

在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类称为回调类,回调类的对象称为回调对象。

例子

开始之前。先想象一个场景:幼稚园的小朋友刚刚学习了10以内的加法。

第一章.故事的缘起

public class Student { private String name=null; public Student(String name) { this.name=name; } public void setName(String name) { this.name=name; } private int calcADD(int a,int b) { return a+b; } public void fillBlank(int a,int b) { int result=calcADD(a,b); System.out.println(name+"心算:"+a+"+"+b+"="+result); } } 

小明同学在填空(fillBlank)的时候,直接心算(clacADD)了一下,得出结果是2,并将结果写在空格里。测试代码如下:

public class Test { public static void main(String[] args) { int a=1; int b=1; Student s=new Student("小明"); s.fillBlank(a,b); } } 

运行结果如下

小明心算:1+1=2

该过程完全由Student类的实例对象单独完成,并未涉及回调机制。

第二章.幼师的找茬

public class Calculator { public int add(int a,int b) { return a+b; } } 

修改Student类,添加使用计算器的方法:

public class Student { private String name=null; public Student(String name) { this.name=name; } public void setName(String name) { this.name=name; } private int calcADD(int a,int b) { return a+b; } private int useCalculator(int a,int b) { return new Calculator().add(a,b); } public void fillBlank(int a,int b) { int result=useCalculator(a,b); System.out.println(name+"使用计算器:"+a+"+"+b+"="+result); } } 

测试代码如下:

public class Test { public static void main(String[] args) { int a=168; int b=291; Student s=new Student("小明"); s.fillBlank(a,b); } } 

运行结果如下:

小明使用计算器:168+291=459

该过程中仍未涉及到回调机制,但是小明的部分工作已经实现了转移,由计算器来协助实现。

第三章.幼师回来了

public class SuperCalculator { public void add(int a,int b,Student xiaoming) { int result=a+b; xiaoming.fillBlank(a,b,result); } } 

小明这边现在已经不需要心算,也不需要使用计算器,因此只需要有一个方法可以向小红寻求帮助就行了,代码如下:

public class Student { private String name=null; public Student(String name) { this.name=name; } public void setName(String name) { this.name=name; } public void callHelp(int a,int b) { new SuperCalculator().add(a,b,this); } public void fillBlank(int a,int b,int result) { System.out.println(name+"求助小红计算:"+a+"+"+b+"="+result); } } 

测试代码如下:

public class Test { public static void main(String[] args) { int a=26549; int b=16487; Student s=new Student("小明"); s.callHelp(a,b); } } 

运行结果为:

小明求助小红计算:26549+16487=43036

执行流程为:小明通过自身的callHelp方法调用了小红(new SuperCalculator())的add方法,在调用的时候将自身的引用(this)当作参数一并传入,小红在使用计算器得出结果之后,回调了小明的fillBlank方法,将结果填在了黑板的空格上。

到这里,回调功能就正式登场了,小明的fillBlank方法就是我们常说的回调函数。

通过这种方式,可以明显的看出,对于完成老师的填空题这个问题上,小明已经不需要等待到加法做完且结果填写在黑板上才能去跟小伙伴撒欢了,填空这个工作由超级计算器小红来做了。回调的优势已经开始体现了。

第4章.门口的婆婆

幼稚园的门口有一个头发花白的老婆婆,每天风雨无阻在那里摆着地摊卖一些快过期的垃圾食品。由于年纪大了,脑子有些糊涂,经常算不清楚自己挣了多少钱。有一天,她无意间听到了小明跟小伙伴们吹嘘自己如何在小红的帮助下与幼师斗智斗勇。于是,婆婆决定找到小红牌超级计算器来做自己的小帮手,并提供一包卫龙辣条作为报酬。小红经不住诱惑,答应了。

回看一下上一章的代码,我们发现小红牌超级计算器的add方法需要的参数是两个整型变量和一个Student对象,但是老婆婆她不是学生,是个小商贩啊,这里肯定要做修改。这种情况下,我们很自然的会想到继承和多态。如果让小明这个学生和老婆婆这个小商贩从一个父类进行继承,那么我们只需要给小红牌超级计算器传入一个父类的引用就可以啦。

不过,实际使用中,考虑到java的单继承,以及不希望把自身太多东西暴漏给别人,这里使用从接口继承的方式配合内部类来做。

换句话说,小红希望以后继续向班里的小朋友们提供计算服务,同时还能向老婆婆提供算账服务,甚至以后能够拓展其他人的业务,于是她向所有的顾客约定了一个办法,用于统一的处理,也就是自己需要的操作数和做完计算之后应该怎么做。这个统一的方法,小红做成了一个接口,提供给了大家,代码如下:

public interface doJob { public void fillBlank(int a,int b,int result); } 

因为灵感来自帮小明填空,因此小红保留了初心,把所有业务当做填空(fillBlank)来做。

同时,小红修改了自己的计算器,使其可以同时处理不同的实现了doJob接口的人,代码如下:

public class SuperCalulator { public void add(int a,int b doJob customer) { int result=a+b; customer.fillBlank(a,b,result); } } 
public class Student { private String name=null; public Student(String name) { this.name=name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a,int b,int result) { System.out.println(name+"求助小红计算:"+a+"+"+b+"="+result); } } public void callHelp(int a,int b) { new SuperCalculator().add(a,b,new doHomeWork()); } } 

老婆婆的:

public class Seller { private String name=null; public Seller(String name) { this.name=name; } public setName(String name) { this.name=name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a,int b,int result) { System.out.println(name+"求助小红算账:"+a+"+"+b+"="+result+"元";) } } public void callHelp(int a,int b) { new SuperCalculator().add(a,b,new doHomeWork()); } } 

测试程序如下:

public class Test { public static void main(String[] args) { int a=56; int b=31; int c=26497; int d=11256; Student s1=new Student("小明"); Seller s2=new Seller("老婆婆"); s1.callHelp(a,b); s2.callHelp(c,d); } } 

运行结果如下:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220799.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午7:37
下一篇 2026年3月17日 下午7:38


相关推荐

  • mqtt安卓客户端_网络抓包工具哪个好

    mqtt安卓客户端_网络抓包工具哪个好MQTT客户端工具介绍概览在学习和使用MQTT的过程中,一个得心应手的客户端工具可以极大的方便使用者进行MQTT特性的探索和功能组件的调试。来自世界各地的开发者们围绕不同操作系统、运行平台,开发出了许多针对MQTT协议的客户端测试工具。这些客户端工具种类繁多,功能侧重点不尽相同,质量层次不齐,因此,对于初学者乃至MQTT专家来说,如何选择一个适用的MQTT客户端工具是一个难题。本篇文章将尽可能的搜集整理,对市面上各类MQTT客户端工具做一个全面的测评以供读者参考。MQTT

    2025年7月7日
    6
  • 最新仿金蝶电商ERP进销存系统软件源码 销售库存仓库财务管理收银系统网络版「建议收藏」

    最新仿金蝶电商ERP进销存系统软件源码 销售库存仓库财务管理收银系统网络版「建议收藏」源码说明:超强的工作流系统,强大的可视化工作流编辑器,灵活自定义表单设计,充分实现企业基于工作流的各项业务管理,与其他模块数据(如HRM等)完美结合。全面综合的任务系统,实现基于信息录入、单据管理、业务协作、工作流转、任务提醒、统计分析等的智能管理。所有单据均支持上传附件功能;且报价单、销售合同、采购订单、发货出库、入库单、派工单等所有模板均支持自定义编辑打印。集成功能实用的CRM系统、进销存系统、生产ERP系统,实现对客户销售、供应商采购、产品物料、库存统计、生产监控等的精细化管理,直观强大的销售

    2022年5月11日
    50
  • fragstats4.2使用

    fragstats4.2使用fragstats 用来计算生态指数 简单方便 1 下载 http www umass edu landeco research fragstats downloads fragstats downloads htmlFragstat 2 软件的安装 1 如果装有 ArcGIS 可以直接使用 2 没有 设置环境变量复制 fragstats bin 所在位置我的电脑 gt 属性 gt 高

    2026年3月19日
    2
  • Visio2013激活_2013 visio 32位

    Visio2013激活_2013 visio 32位转载的博客,记录下来,便于后面查找。from: http://blog.csdn.net/keenweiwei/article/details/42780805/环境是win7,64bit装了visio2013,可以却不能用它来画图,在网上找了一些激活成功教程工具,大都不能解决问题。网上不靠谱的广告型文章太多了,比较头痛。所幸,终于找到正确的激活成功教程工具KMSpico_set…

    2022年10月5日
    3
  • python-Numpy学习之(一)ndim、shape、dtype、astype的用法

    python-Numpy学习之(一)ndim、shape、dtype、astype的用法python-Numpy学习之(一)ndim、shape、dtype、astype的用法参考网址:https://blog.csdn.net/Da_wan/article/details/80518725本文介绍numpy数组中这四个方法的区别ndim、shape、dtype、astype。1.ndimndim返回的是数组的维度,返回的只有一个数,该数即表示数组的维度。2….

    2022年6月14日
    31
  • VsVim的vimrc

    VsVim的vimrc给VisualStudio安装VsVim后可在VS中使用vim的便捷编辑功能,很强大。同时也可通过vimrc文件来做些特殊配置,vimrc的搜索路径可通过在编辑器中输入“:set”查看。我的vimrc搜索路径如下:vimrcpaths=”C:\Users\chenbo;C:\Users\chenbo\vimfiles;C:\Users\chenbo”在C:\Users\Chenbo…

    2022年6月10日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号