回调?是什么,简单讲解一下-程序员宅基地

技术标签: Java  C++  java  开发语言  

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed。
回调就是把一个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。

使用回调的场景

在调用一个函数之后,需要在函数执行中或执行后,将执行结果或状态再传递给调用者并进行一系列后续操作时,可以使用回调机制。通常是:

  1. 执行某个操作需要耗时,异步执行后进行回调;
  2. 调用者不再关心回调函数中进行的后续操作;
  3. 程序需要监听函数中某个动作的完成,从而进行下一步操作

回调在编程语言中的体现

在函数式编程语言,如 JavaScript 中,回调体现为:


// 被调用的函数:控制台打印 a 之后,调用 fun 函数
function print(a, fun){
    
	console.log(a);
	fun();
}

function callback(){
    
	console.log("调用回调函数:callback")
}

// 主函数
function main(){
    
   // 调用print,传入参数a 和一个回调函数
   // 回调函数可以是已经声明的函数
   print("参数a", callback)
   // 也可以是临时实现的匿名函数
   print("参数a", function(){
    
   		console.log("调用匿名回调函数")
   })
}

在 C 语言中,回调函数以 函数指针 的形式作为参数传入:

#include <stdio.h>

// 函数 fun 接收两个参数
// 一个整型数 a,一个函数指针(指向一个无返回值,参数为一个 int 的函数)
// 打印完 a 的值之后,将 a 进行一顿乱七八糟的运算之后,回调给函数指针 c 指向的函数
void fun(int a, void (*c)(int))
{
    
    printf("\nfun接收参数:%d\n", a);
    a = a * 1 - 5 + 6 / 7 * 8;
    (*c)(a);
}

void callback1(int a)
{
    
    printf("回调结果:%d\n", a);
}

void callback2(int a)
{
    
    printf("回调2结果:%d\n", a * 2);
}

int main()
{
    
    fun(2, callback1);
    fun(2, callback2);
}

运行结果为:
在这里插入图片描述
这里主要讲解一下在 java 中的回调机制,由于 java 不是函数式编程语言,不能将函数作为参数传递(包括 lambda 本质也是函数式接口的实现),所以在 java 中回调以 回调接口 的形式实现。

即:将一个接口的实现类的实例作为参数传递,将这个接口中方法作为回调函数进行调用

这里给定一个案例:
学生参加考试计算加法,他们计算的结果需要回调给阅卷老师或阅卷系统,也就是我们的回调接口,回调接口在对学生的的答案进行评价。详细请看以下代码:

public class Main {
    

    // 回调接口,用于判断学生计算的结构是否正确,
    // 这里可以理解为【改卷老师】或者【改卷系统】
    public interface CallBack {
    
        void call(int result);
    }

    // 学生 A
    static class StudentA {
    
        // 学生 A 智商有问题,加法从来算不对
        public void add(int a, int b, CallBack callBack) {
    
            int result = a + b + 1;
            System.out.printf("A 交卷:%d+%d=%d%n", a, b, result);
            callBack.call(result);
        }
    }

    // 学生 B
    static class StudentB {
    
        // 学生 B 比较正常,加法从来没算错过
        public void add(int a, int b, CallBack callBack) {
    
            int result = a + b;
            System.out.printf("B 交卷:%d+%d=%d%n", a, b, result);
            callBack.call(result);
        }
    }

    public static void main(String[] args) {
    

        // 有两个学生参加考试
        StudentA a = new StudentA();
        StudentB b = new StudentB();

        // 题目给定加法的两个数
        final int one = 1, tow = 2;

        // 指定回调类
        CallBack c = new CallBack() {
    
            // call 方法指定接收到计算结果时,对该结果做出的反应
            @Override
            public void call(int result) {
    
                System.out.print("评语:");
                // 结果正确
                if (result == (one + tow)) {
    
                    System.out.println("你真棒");
                } 
                // 结果错误
                else {
    
                    System.out.println("emmm....");
                }
            }
        };

        // 上面的 callback 可以简写为 lambda 表达式
        CallBack cShort = result -> System.out.println("评语:" + (result == (one + tow) ? "你真棒" : "emmm...."));

        a.add(one, tow, cShort);
        b.add(one, tow, cShort);
    }

运行结果:
在这里插入图片描述

为什么使用回调

既然是接收上一个函数的运行结果,为什么使用回调,用返回值不行吗??

  1. 不是所有函数或者方法都有返回值,并且返回值只有一个,回调函数可以具有多个参数,可以对多个数据进行处理;
  2. 返回值需要等待函数执行完成才能返回,而回调可以使用多线程异步执行,不必等待函数执行;
  3. 回调函数可以不只一个,例如可以指定同时指定执行成功时的 success 回调函数和执行失败时的 fail 回调函数,被调用的函数甚至可以选择不执行回调。回调什么时候执行、是否执行、如何执行都与函数调用者解耦,函数调用者只需将其作为参数传入就行了,至于后续的操作,调用者通常不再关心。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44155115/article/details/124654169

智能推荐

华为手表哪款搭载鸿蒙系统,华为Watch GT 2渲染图曝光:首款搭载鸿蒙系统的智能手表...-程序员宅基地

文章浏览阅读230次。近日华为官宣将于9月19日在德国慕尼黑召开新品发布会,正式推出备受关注的新款旗舰Mate 30系列。与此同时华为还将会推出新款Watch GT 2智能手表,这可能会是首款搭载鸿蒙系统的华为智能手表。今天德国科技媒体WinFuture带来了关于该智能手表的高清渲染图,让我们一起来看看。据悉这款智能手表并不依赖于谷歌的Wear OS,Watch GT 2手表可以在没有和尚未发布的Mate 30系统配对..._华为2代手表是鸿蒙吗

修改字符串的方法_ollydbg修改成更长的字符串-程序员宅基地

文章浏览阅读3k次。现已学到2种在ollydbg中修改字符串的方法。1.直接修改字符串缓冲区。2.在其他内存区域生成新字符串并传递给消息函数。第一种方法比较简单,不过新字符串的长度不应超过旧字符串的长度,倘若超过,就有可能损坏了字符串所在内存下面的数据。第二种方法需要寻找未填充的缓冲区,在这里写入新字符串并将地址作为参数传递给消息函数,新字符串可以是任意长度。但也需要考虑下新缓冲区的位置问题(涉及到p_ollydbg修改成更长的字符串

技术干货 | Docker 容器逃逸案例汇集-程序员宅基地

文章浏览阅读2.4w次。当获得一个Webshell,我们的攻击点可能处于服务器的一个虚拟目录里,一台虚拟机或是一台物理机,甚至是在一个Docker容器里。假设,我们获取的Webshell就处于Docker容器里,那么,我们该如何破局呢?Docker 容器逃逸案例:1、判断是否处于docker容器里2、配置不当引起的逃逸Docker Remote API 未授权访问docker.s...

iso文件:抱歉,装载文件时出现问题_抱歉,装载文件时出现问题-程序员宅基地

文章浏览阅读2.5w次,点赞3次,收藏7次。问题描述右击 ISO 文件选择“装载”,便会弹出一个消息框报错,这该怎么办呢? 解决方法网上有很多的解决办法,例如:更改驱动器号和路径或者是更改注册表 但是我感觉应该没有那么多问题,继续在网上找解决的方法,终于找到一个简单的方法,具体方法如下: 1.右键点属性 2.详细信息 一般不能装载的都是属性都是RAP,可以装载的是RA 3.选择删除属性和个人信息 4.接下来会生成一个副本_抱歉,装载文件时出现问题

ehcache作为分布式缓存的研究-程序员宅基地

文章浏览阅读59次。ehcache支持两种拓扑结构,一种是Distributed Caching,另一种是Replicated CachingDistributed Caching这和一般意义上的分布式缓存非常类似,这一类型的缓存是有client-server之分的,application通过client向server端请求缓存数据,在server端,数据是散列到多个节点上的。具体而准确的拓扑结构见下图(该图正是..._ehcache 分布式模式 docker

ECCV 2022 | 视频插帧中的实时中间流估计-程序员宅基地

文章浏览阅读710次。概述视频插帧算法旨在视频的相邻帧之间生成若干个中间帧。它被广泛用于视频处理,多媒体播放器和显示设备上。本文提出了一种基于实时中间流估计的视频插帧算法 RIFE,包括一个端到端的高效的中间流估计网络 IFNet,以及基于特权蒸馏的光流监督框架。RIFE 支持在两帧之间的任意时刻点插帧,在多个数据集上达到了最先进的性能且不依赖于任何的预训练模型。相比目前流行的 SuperSlomo 和 DAIN 技术..._光流逆转

随便推点

python做小程序-抖音最火的整蛊表白小程序如何做出来的?教你用python做出-程序员宅基地

文章浏览阅读328次。考虑一下利用Python制作一个整蛊、木马软件,我提供思路。(清楚到没学过编程的人也理解)1、首先一个黑客做一个整蛊或者木马软件,一定不会让你能够关闭它。2、里面经常会附带欺骗的方法。3、最终实现某种目的。前段时间在抖音上看到个有趣的程序,看样子是VB写的,首先就要用到欺骗的方法,利用软件名称欺骗目标点击软件,打开后出现一个标签、两个按钮。标签上写的是:我爱你,你爱我吗?按钮:一个写爱,一个是不爱..._python打包表白小程序代码

linux常用命令-curl命令详解(超详细)_linux curl命令详解-程序员宅基地

文章浏览阅读4.1k次,点赞6次,收藏13次。本文介绍了 `curl` 命令的常用选项和参数,以及示例用法。`curl` 是一个功能强大的命令行传输工具,用于发送请求和下载文件。常用选项包括保存文件、发送 POST 请求、自定义头部信息、指定请求方法、身份验证、跟随重定向、忽略 SSL 证书验证、静默模式和详细模式等。示例用法涵盖了下载文件、发送 POST 请求、附加头部信息、指定请求方法、身份验证、跟随重定向、忽略 SSL 证书验证、静默模式和详细模式等。这些选项和参数可以根据具体需求和场景进行灵活运用。_linux curl命令详解

golang微服务框架go-zero系列-2:在go-zero中使用jwt-token鉴权实践-程序员宅基地

文章浏览阅读2.6k次。阅读本文前你需要阅读金光灿灿的Gorm V2+适合创业的golang微服务框架go-zero实战创建项目生成go.mod文件以如下指令创建项目mkdir jwttokencd jwttokengo mod init jwttoken定义user.api本文设计API如下描述格式方法参数返回是否需要鉴权用户登录/open/authorizationpostmobile:手机号,passwd:密码,code:图片验证码id:用户ID,token:用户t

深度学习框架-Keras:特点、架构、应用和未来发展趋势_keras框架-程序员宅基地

文章浏览阅读1.5k次。深度学习是一种新兴的技术,已经在许多领域中得到广泛的应用,如计算机视觉、自然语言处理、语音识别等。Keras是深度学习的一种重要框架,它具有许多优点,如简单易用、模块化、多后端支持等。Keras核心是Keras的主要库,它提供了一些高级API,如Sequential和Functional API,可以方便地构建和训练神经网络模型。语音识别是另一个深度学习的重要领域,Keras可以在语音识别中得到广泛应用。Keras是一种简单易用的深度学习框架,它提供了一些高级API,可以方便地构建和训练神经网络模型。_keras框架

点滴学习Linux --- Vim 代码块缩进快捷键_linux代码缩进快捷键-程序员宅基地

文章浏览阅读6k次,点赞4次,收藏3次。使用vim进行代码编写时,我们进行需要对代码进行对其。本人之前采用的都是笨方法,一行一行的对其,这样不但效率低,而且还可能出现错误,那vim中有没有自带代码缩紧功能呢?答案是肯定的。1.使用Shift +V 选择你要缩进的行2.按下‘=’即可是不是很简单?_linux代码缩进快捷键

Docker Review - Docker 概念 & 入门篇_review docker tool-程序员宅基地

文章浏览阅读1.7w次。文章目录概述What's Docker ?概述使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力。在云服务概念兴起之后,Docker的使用场景和范围进一步发展,如今在微服务架构越来越流行的情况下,微服务+Docker的完美组合,更加方便微服务架构运维部署落地。What’s Docker ?..._review docker tool