回调函数&&回调机制

2023-11-16

所谓回调, 定义是“一个方法的指针传递给事件源,当某一事件发生时用来调用这个方法。”

比如客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。例如Win32下的窗口过程函数就是一个典型的回调函数。一般说来,C不会自己调用B,C提供B的目的就是让S来调用它,而且是C不得不提供。由于S并不知道C提供的B姓甚名谁,所以S会约定B的接口规范(函数原型),然后由C提前通过S的一个函数A告诉S自己将要使用B函数,这个过程称为回调函数的注册,A称为注册函数

总的来说:回调函数就是那些自己写的,但是不是自己来调,而是给别人来调的函数。而注册函数是别人的。

回调一般用于层间协作,上层将本层函数安装在下层,这个函数就是回调函数,而下层在一定条件下触发回调,例如作为一个驱动,是一个底层,他在收到一个数据时,除了完成本层的处理工作外,还将进行回调,将这个数据交给上层应用层来做进一步处理,这在分层的数据通信中很普遍。 
   其实回调和API非常接近,他们的共性都是跨层调用的函数。但区别是API是低层提供给高层的调用,一般这个函数对高层都是已知的;而回调正好相反,他是高层提供给底层的调用,对于低层他是未知的,必须由高层进行安装,这个安装函数其实就是一个低层提供的API(个人理解为就是注册函数),安装后低层不知道这个回调的名字,但它通过一个函数指针来保存这个回调,在需要调用时,只需引用这个函数指针和相关的参数指针

消息响应函数就可以看成是回调函数,因为是让系统在合适的时候去调用。只不过消息响应函数就是为了处理消息的,所以就拿出来单做一类了。其实本质上就是回调函数。但是回调函数不是只有消息响应函数一种,比如在内核编程中,驱动程序就要提供一些回调函数,当一个设备的数据读写完成后,让系统调用这些回调函数来执行一些后续工作。

   其实:回调就是该函数写在高层,低层通过一个函数指针保存这个函数,在某个事件的触发下,低层通过该函数指针调用高层那个函数


C语言中回调函数解释:

我们调用函数的方法有两种:

        直接调用:在函数A的函数体里通过书写函数B的函数名来调用之,使内存中对应函数B的代码得以执行。这里,A称为“主叫函数”(Caller),B称为“被叫函数”(Callee)。

      间接调用:在函数A的函数体里并不出现函数B的函数名,而是使用指向函数B的函数指针p来使内存中属于函数B的代码片断得以执行。

比起直接调用来,间接调用的确麻烦,那为什么还要使用间接调用呢?原因很简单——直接调用把函数名都写进函数体了,经过编译器那么一编译,板上钉钉,A注定调用的是B了,这样的程序只能按照程序员事先设计好的流程执行下去,太呆板了。此时,间接调用的巨大灵活性就显现出来了。想一想,如果p是函数A的一个参数(参数是变量,是变量就可以变的!),那么程序的最终用户完全可以通过操作来改变p的指向——这样,A在通过p调用函数的时候就有机会调用到不同的函数,这样程序的实用性扩展性就强多了。

在WINDOWS中,程序员想让系统DLL调用自己编写的一个方法,于是利用DLL当中回调函数的接口来编写程序,使它调用,这个就称为回调。在调用接口时,需要严格的按照定义的参数和方法调用,并且需要处理函数的异步,否则会导致程序的崩溃。这样的解释似乎还是比较难懂,这里举个简单的例子,程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用自己的程序b中的一个方法,于是,他通过a中的接口回调自己b中的方法。目的达到。在C/C++中,要用回调函数,被调函数需要告诉调用者自己的指针地址,但在JAVA中没有指针,怎么办?我们可以通过接口(interface)来实现定义回调函数。

正常情况下开发人员使用已经定义好的API,这个过程叫Call。但是有时这样不能满足需求,就需要程序员注册自己的程序,然后让事先定义好API在合适的时候调用注册的方法,这叫CallBack。

“通常大家说的回调函数一般就是按照别人(李四)的定好的接口规范写等待别人(张三)调用的函数,在C语言中,回调函数通常通过函数指针来传递;在Java中,通常就是编写另外一个类或类库的人(李四)规定一个接口,然后你(张三)来实现这个接口,然后把这个实现类的一个对象作为参数传给别人(例如王五)的程序,王五的程序必要时就会通过那个接口来调用你编写的函数。


   下面举个通俗的例子:
   某天,我打电话向你请教问题,当然是个难题,^_^,你一时想不出解决方法,我又不能拿着电话在那里傻等,于是我们约定:等你想出办法后打手机通知我,这样,我就挂掉电话办其它事情去了。过了XX分钟,我的手机响了,你兴高采烈的说问题已经搞定,应该如此这般处理。故事到此结束。这个例子说明了“异步+回调”的编程模式。其中,你后来打手机告诉我结果便是一个“回调”过程;我的手机号码必须在以前告诉你,这便是注册回调函数;我的手机号码应该有效并且手机能够接收到你的呼叫,这是回调函数必须符合接口规范。

java回调机制:

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

同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;

回     调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;

异步调用:一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。

回调和异步调用的关系非常紧密:使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。 

用Java里的例子:

public interface ICallBack//接口,规范需要有的函数
{
       public void postExec();//需要回调的方法
}

另外的一个类:

public class FooBar
{            

      private  ICallBack callBack;
      public   void setCallBack(ICallBack callBack)
                   {
                             this.callBack = callBack;
                             doSth();
                    }
      public  void doSth()
                    {
                            callBack.postExec(); //调用回调函数
                    }
}

第二个类在测试类里面,是一个匿名类:

public class Test
{
       public static void main(String[] args)
       {
              FooBar foo = new FooBar();

              //匿名类把自己作为参数传给setCallBack函数

              foo.setCallBack(new ICallBack()        //此处的ICallBack是一个特殊类:实现了IcallBack接口的匿名类。

                                                     {
                                                            public void postExec()
                                                                            {              
                                                                                 System.out.println("在Test类中实现这个接口,但由FooBar对象调用");
                                                                             }
                                                     }

                                        );
       }
}

上面的代码:

 1.三个类:匿名类和FooBar,还有一个测试类

 2.匿名类实现接口ICallBack(在test测试的main方法中用匿名类的形式实现)

 3.FooBar 拥有一个参数为ICallBack接口类型的函数setCallBack(ICallBack   

 4.匿名类运行时调用FooBar中setCallBack函数,把自己当做参数传入setCallBack

 5.FooBar已取得匿名类,就可以随时回调匿名类中所实现的ICallBack接口中的方法postExec


假设有接口名为ICallBack 其中有方法名为postExec()。有类Myclass 实现了该接口,也就是实现了postExec()这个方法。现在有另一个类FooBar它有个方法setCallBack(ICallBack callBack),并且setCallBack方法调用了callBack的postExec()方法。
如果现在,我们使用一个Myclass 的实例myClass(也就是那个匿名类),将它作为参数带入到setCallBack(ICallBack)方法中,我们就说setCallBack(ICallBack)方法回调了myClass的postExec()方法。




 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

回调函数&&回调机制 的相关文章

  • 【C语言scanf函数用法】

    本节介绍输入函数 scanf 的用法 scanf 和 printf 一样 非常重要 而且用得非常多 所以一定要掌握 概述 scanf 的功能用一句话来概括就是 通过键盘给程序中的变量赋值 该函数的原型为 include
  • 深度学习中30个关于数据的问题

    1 下面的数据是线性可分的嘛 否 2 下面哪个是通用的模型逼近器 A Kernel SVM B Neural Networks C Boosted Decision Trees D All of the above D 以上所有都可以得到一
  • Run-Time Check Failure #0 错误

    使用VS 遇到过一个错误 如下图 文字描述是这样的 Run Time Check Failure 0 The value of ESP was not properly saved across a function call This i
  • matlab中Img(:,:,n)函数的说明

    Img n 中 n可以取1 2 3分别代表img图像的第1 2 3通道 即对应着R G B三种颜色 也就是说 Img 1 是红色分量图像 Img 2 是绿色分量图像 Img 3 是蓝色分量图像 具体也可通过如下一段函数定义可以看出 img
  • STM32的PWM相关函数TIM_SetCompare1的一定理解

    void TIM SetCompare1 TIM TypeDef TIMx uint16 t Compare1 Check the parameters assert param IS TIM LIST8 PERIPH TIMx Set t
  • 游戏中关于跳跃的函数图像的推导以及应用

    跳跃应该是游戏开发中一个最常见的功能之一 实现的方法也有很多 这里我来讲一个我以前用的一个方法 正常的跳跃 如果使用物理引擎的话 就直接给一个向上的力就可以了 但是有一些游戏 例如跑酷 角色的移动速度都是越来越快的 而如果还是只给一个向上的
  • 关键字static、Const、Volatile的作用是什么

    关键字static的作用是什么 在C语言中 关键字static有三个明显的作用 1 在函数体 一个被声明为静态的变量在这一函数被调用结束后不释放其存储空间 定义为static的局部变量的存储在全局区 静态区 而一般的局部变量存储在栈中 2
  • 自学C之递归理解

    一 理解概念 C语言允许一个函数调用自身 这种过程被称为递归 Recursion 程序使用递归处理特殊的问题 如阶乘 Ackermann函数 反序等等 实际上 如果不考虑运行时内存的开消 任何使用赋值语句 if else和while结构的函
  • python3 Flask 简单入门

    flask是python里面最轻便的框架 这里演示了访问主页 登陆成功 登陆失败的页面显示 在编写URL处理函数时 除了配置URL外 从HTTP请求拿到用户数据也是非常重要的 Web框架都提供了自己的API来实现这些功能 Flask通过re
  • ##顺序表 编码##

    ifndef LIST H define LIST H class List public List int size List 析构函数 void ClearList 清空线性表 bool ListEmpty 判断线性表是否为空 int
  • Lua封装延时执行函数

    延时执行函数 function delayTimeGuideEvent target func times 延迟时间执行函数 local delaytime 1 if times then delaytime times end getRo
  • 实验6-6 使用函数验证哥德巴赫猜想 (20分)

    http pta patest cn pta test 13 exam 3 question 478 include
  • RxJava 事件流之聚合

    Aggregation 前面介绍了如何过滤掉不需要的数据 如何根据各种条件停止发射数据 如何检查数据是否符合某个条件 这些操作对数据流来说都是非常有意义的 本节介绍如何根据数据流中的数据来生成新的有意义的数据 本节的操作函数会使用源 Obs
  • linux笔记之初次接触信号

    一 关于信号概念 1 信号是Linux所使用的进程间通信的最古老的方式 它是在软件层次上对中断机制的一种模拟 是一种异步通信的方式 一个完整的信号周期包括三个部分 信号的产生 信号在进程中的注册 信号在进程中的注销 执行信号处理函数 如下图
  • 高数:第一章:函数、极限、连续

    文章目录 一 函数 1 函数的概念 基本初等函数 初等函数 2 函数的性质 函数四性态 1 单调性 2 奇偶性 3 导函数的奇偶性 3 周期性 4 有界性 5 对称性 3 基本不等式 4 开根要带绝对值 二 极限 1 极限的概念 数列极限
  • 函数,形参 实参,递归

    打开网页 include
  • 最小二乘法–高斯牛顿迭代法

    最小二乘法 高斯牛顿迭代法 本文将详解最小二乘法的非线性拟合 高斯牛顿迭代法 1 原理 高斯 牛顿迭代法的基本思想是使用泰勒级数展开式去近似地代替非线性回归模型 然后通过多次迭代 多次修正回归系数 使回归系数不断逼近非线性回归模型的最佳回归
  • Matrix calculus(矩阵微积分)(前四节)

    原文地址 https en wikipedia org wiki Matrix calculus 注 不要把它和几何运算或者是向量运算混淆 前言 在数学中 矩阵微积分是进行多变量微积分的一种特殊符号 特别是在矩阵的空间上 它将关于许多变量的
  • Glide图片加载回调监听

    前两篇文章从源码的角度对Glide的加载流程进行了分析 这篇文章将对Glide的回调进行总结 1 方法一 设置图片中监听 方法一使用的是SimpleTarget类 他继承自BaseTarget 需要重写onResourceReady方法 o
  • [从零开始学习FPGA编程-38]:进阶篇 -语法-函数与任务

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 目录 前言 第1章 什么是函数Function 1 1 什么是函数 1 2 函

随机推荐

  • Unity 获取Animtor Controller 动画控制器的参数,层级

    获取Animator中的Parameters参数 Trigger Int Float等类型 UnityAPI Animator parameters 获取所有参数 获取Layer层 UnityAPI Animator layerCount
  • sql 自定義百分比轉換小數函數

    CAST 和 CONVERT 函数 Percentage DECLARE dec decimal 5 3 var varchar 10 hun decimal 5 1 set dec 0 025 set hun dec 100 set va
  • 通过vue和element-ui框架写前台

    首先我们运维一般写web界面很多都会使用bootstrp jquery 现在vue其以简单 不用直接操作dom 深受广大非前端爱好者的喜欢 前端只用写界面 后台关注界面就可以了 实现前后台分离 flask如何引入vue js和element
  • shell脚本启动java类或者jar包实践

    1 直接在shell脚本中执行class文件 代码目录如下 在目录下执行bash test sh命令 shell脚本test sh的代码如下 java Xmx2048m Xms2048m XX MaxNewSize 2048m XX Max
  • 第二篇,ESP8266烧录固件 各种版本解决方案 mqtt 安信可固件 记录于2021年6月30日

    1 硬件连接准备 1 1对于esp8266 01和esp8266 01s 特别需要进行注意 RX接TX TX接RX 3 3V接3 3V GND接GND IO0接GND 一定要注意这一步 烧录的时候如果不行话 直接重新上电就可以 反复几次 就
  • Windows server 服务器com安全编辑限制选项灰色

    在一次Windows server 系统运维中 项目实施方搭建OPC时遇到了com 安全编辑限制选项灰色的问题 当时百度查找了很多但是也没查到 但是能确定应该是组策略和注册表中用户administrator权限不够的问题 查找资料中发现Dc
  • 2021->2022

    也就随便写写了 记得去年的年终和期望目标 我写了好多个方面的自我剖析 可能大概有三四千字吧 再回去看看 还是水了一些 这很正常 大多数人都是这样的 况且我比较佛系 复盘还是要的 期望还是要提的 虽然明知一年过后 可能达成的不多 但这也是一次
  • 医疗知识中台白皮书

    该白皮书显示 医疗行业平均医护人员供给不足 优质医疗资源过于聚集 医疗资源质量短期难以大幅提高等问题突出 与此同时 遵循医疗逻辑的智能化开放平台 医疗知识中台 正在成为解决这一难题的突破口 关注公众号 互联互通社区 回复 ZTZL053 获
  • 通用网关接口(摘录)

    维基百科 自由的百科全书 通用网关接口 Common Gateway Interface CGI 是一种重要的互联网技术 可以让一个客户端 从网页浏览器向执行在 Web 服务器 上的程序 请求数据 CGI 描述了客户端和这个程序之间传输数据
  • 【Python-利用动态二维码传输文件(四)】使用pyautogui库录屏(连续截图),然后利用OpenCV逐张读取截图,识别当中的二维码信息,并把信息重组成原文件

    程序示意图 目录 一 使用pyautogui库 对电脑屏幕进行录屏 二 使用OpenCV库对100帧截图进行识别 并与原29帧二维码图片内含信息进行比对 三 把获取的100帧二维码信息去重 并保持原来顺序 重组成原来的文件 四 小结和完整代
  • Java前后端分离动态国际化(动态配置扩展性高)

    介绍 主要是针对前后端分离场景国际化系统设计 亮点 1 动态国际化配置 2 可维护性 3 国际化数据池化 性能高 4 后端数据内容动态国际化 5 提供前台动态国际化数据 6 后台异常国际化处理 7 可动态添加国际化的语种 8 国际化配置集中
  • React中路由组件的lazyLoad

    1 通过React的lazy函数配合import 函数动态加载路由组件 gt 路由组件代码会被分开打包 const Login lazy gt import pages Login 2 通过
  • 生成一定相关性的二元正态分布

    生成一定相关性的二元正态分布 摘要 二元正态分布 二元正态分布概率密度函数 二元正态分布随机数的生成 程序实现 多元正态分布的情况 生成服从 N
  • 【http】10,000 milliseconds timeout on connection http-outgoing-0 [ACTIVE]

    1 概述 本日使用http远程连接获取远程接口信息报错 10 000 milliseconds timeout on connection http outgoing 0 ACTIVE 022 12 23 09 54 15 181 ERRO
  • C潜规则篇之防止重定义

    C程序编译时常出现类似xxx redefinition错误 除了模块间的命名冲突 命名污染及static 问题多数与头文件管理有关 大型C工程的头文件管理很麻烦 C源文件往往包含很多头文件 头文件又包含其他头文件 形成复杂的嵌套包含 C没有
  • Android 逆向工程,反编译心得

    前言 apk的反编译是我们在Android开发中绕不开的一个坎 对于反编译这门技术 我们应该抱着学习的态度 学的越多 也越能防备别人反编译我们 这就是所谓的知己知彼吧 哈哈 需要准备的工具 Apktool 解包和重新打包都需要它 dex t
  • 在什么情况下、使用python类的使用-使用Python编程时的10个注意事项

    原标题 使用Python编程时的10个注意事项 1 初始变化量 在Python里 一个表达式中的名字在它被赋值之前是没法使用的 这是有意而为的 这样能避免一些输入失误 同时也能避免默认究竟应该是什么类型的问题 0 None 记住把计数器初始
  • iOS Provisioning Profile(Certificate)与Code Signing详解

    引言 关于开发证书配置 Certificates Identifiers Provisioning Profiles 相信做iOS开发的同学没少被折腾 对于一个iOS开发小白 半吊子 比如像我自己 抑或老兵 或多或少会有或曾有过以下不详 疑
  • “Intel VT-x处于禁用状态”如何处理

    在安排虚拟机时 出现Intel VT x处于禁用状态时 第一步 进入bios页面 就是重装系统的那个页面 有的电脑是F1 F2 F10 F12 具体多少上网查查就行了 将intel Virtual Technology改成enabled 第
  • 回调函数&&回调机制

    所谓回调 定义是 一个方法的指针传递给事件源 当某一事件发生时用来调用这个方法 比如客户程序C调用服务程序S中的某个函数A 然后S又在某个时候反过来调用C中的某个函数B 对于C来说 这个B便叫做回调函数 例如Win32下的窗口过程函数就是一