Java回调函数的理解与实现

回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。

在Java里面,我们使用接口来实现回调。举个例子

所谓的回调,就是程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用自己的程序b中的一个方法,于是,他通过a中的接口回调自己b中的方法。

举个例子:

1.  首先定义一个类Caller,按照上面的定义就是程序员A写的程序a,这个类里面保存一个接口引用。

public class Caller {
    private MyCallInterface callInterface;

    public Caller() {
    }

    public void setCallFunc(MyCallInterface callInterface) {
        this.callInterface = callInterface;
    }

    public void call() {
        callInterface.printName();
    }
}

2.  接口的定义,方便程序员B根据定义编写程序实现接口。

public interface MyCallInterface {
    public void  printName();
}

3.  第三是定义程序员B写的程序b

public class Client implements MyCallInterface {

    @Override
    public void printName() {
        System.out.println("This is the client printName method");
    }
}

4.  测试

public class Test {
    public static void main(String[] args) {
        Caller caller = new Caller();
        caller.setCallFunc(new Client());
        caller.call();
    }
}

这样我们可以看到程序a中保留有接口成员变量,使得程序a可以通过这个接口变量调用这个接口任意实现类的方法。而程序b被调用的方法就是回调函数。

接下来在看一个具体的实现:

下面使用java回调函数来实现一个测试函数运行时间的工具类:

如果我们要测试一个类的方法的执行时间,通常我们会这样做:

public   class  TestObject {
    /**
     * 一个用来被测试的方法,进行了一个比较耗时的循环
     */
    public   static   void  testMethod(){
        for ( int  i= 0 ; i< 100000000 ; i++){  

        }
    }
    /**
     * 一个简单的测试方法执行时间的方法
     */
    public   void  testTime(){
        long  begin = System.currentTimeMillis(); //测试起始时间
        testMethod(); //测试方法
        long  end = System.currentTimeMillis(); //测试结束时间
        System.out.println("[use time]:"  + (end - begin)); //打印使用时间
    }  

    public   static   void  main(String[] args) {
        TestObject test=new  TestObject();
        test.testTime();
    }
}

下面我们来做一个函数实现相同功能但更灵活:

首先定一个回调接口:

public   interface  CallBack {
    //执行回调操作的方法
    void  execute();
}  

然后再写一个工具类:

public   class  Tools {
    /**
     * 测试函数使用时间,通过定义CallBack接口的execute方法
     * @param callBack
     */
    public   void  testTime(CallBack callBack) {
        long  begin = System.currentTimeMillis(); //测试起始时间
        callBack.execute(); ///进行回调操作
        long  end = System.currentTimeMillis(); //测试结束时间
        System.out.println("[use time]:"  + (end - begin)); //打印使用时间
    }  

    public   static   void  main(String[] args) {
        Tools tool = new  Tools();
        tool.testTime(new  CallBack(){
            //定义execute方法
            public   void  execute(){
                //这里可以加放一个或多个要测试运行时间的方法
                TestObject.testMethod();
            }
        });
    }
}

一个待测试的,较耗时的方法:

public   class  TestObject {
    /**
     * 一个用来被测试的方法,进行了一个比较耗时的循环
     */
    public   static   void  testMethod(){
        for ( int  i= 0 ; i< 100000000 ; i++){  

        }
    }
}

这里我们没有写程序b去实现Callback接口,而是通过匿名内部类的方法来实现。同样也实现了回调函数。

之后我们看看为什么要使用回调函数:

所谓回调函数就是A调用了B,B在适当的时候又反回去调用A。多数时候因为是单线程,A没有必要等B来调用它,因为A在调用完B之后完全可以调用自己需要的操作。所以回调多见于事件驱动机制里。因为A在调用完B之后不知道B什么时候会完成,所以A不知道B什么时候会完成。而唯一知道B什么时候完成的当然是B自己了,所以当B完成的时候会通过一个回调函数通知A,自己已经完成了,这时候A才知道该进行下面的操作。如果不这样的话,A就只能不断地询问B是不是已经完成了(就是轮询),可见是效率非常低的,实现也很麻烦。

回调通常是在两个不同的线程间需要同步的情况下才出现的,但是很多时候又没有必要用信号量去进行真正的线程同步,因为会很复杂,而且没有必要。所以有了回调。至于回调要干的事情,当然是你自己决定了。

说一下同步回调和异步回调:

同步指的是调用一个方法,调用方要等待该方法所执行的任务完全执行完毕,然后控制权回到调用方;异步指的是调用一个方法,调用方不等该方法执行的任务完毕就返回,当任务执行完毕时会自动执行调用方传入的一块代码。

同步:

void runTask {
  doTask1()
  doTask2()
}

同步调用,执行完 doTask1 在执行 doTask2

异步

doTask1(new Callback() {
  void call() {
    doTask3()
  }
});
doTask2();

异步回调,会同时执行 doTask1 和 doTask2, 在执行完 doTask1 后执行 doTask3

同步调用适合执行耗时短的任务,异步回调适合执行耗时长的任务,而且调用它之后调用的任务没什么关系。

看一个异步回调的案例:

回调接口类:

/**
 * 回调模式-回调接口类
 */
public interface CSCallBack {
    public void process(String status);
}

模拟客户端:

/**
 * 回调模式-模拟客户端类
 */
public class Client implements CSCallBack {

    private Server server;

    public Client(Server server) {
        this.server = server;
    }

    public void sendMsg(final String msg){
        System.out.println("客户端:发送的消息为:" + msg);
        new Thread(new Runnable() {
            @Override
            public void run() {
                server.getClientMsg(Client.this,msg);
            }
        }).start();
        System.out.println("客户端:异步发送成功");
    }

    @Override
    public void process(String status) {
        System.out.println("客户端:服务端回调状态为:" + status);
    }
}

模拟服务端:

/**
 * 回调模式-模拟服务端类
 */
public class Server {

    public void getClientMsg(CSCallBack csCallBack , String msg) {
        System.out.println("服务端:服务端接收到客户端发送的消息为:" + msg);

        // 模拟服务端需要对数据处理
        try {
            Thread.sleep(5 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("服务端:数据处理成功,返回成功状态 200");
        String status = "200";
        csCallBack.process(status);
    }
}

测试类:

/**
 * 回调模式-测试类
 */
public class CallBackTest {
    public static void main(String[] args) {
        Server server = new Server();
        Client client = new Client(server);

        client.sendMsg("Server,Hello~");
    }
}

原文地址:https://www.cnblogs.com/winterfells/p/9480140.html

时间: 2024-10-21 17:47:12

Java回调函数的理解与实现的相关文章

转Java 回调函数的理解

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

Java回调函数的理解

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

Java 回调函数

回调函数 我对回调函数的理解 假设: 我的车在家里,现在已经坏了,我打电话给万能的维修工,我告诉他,嘿!哥来帮我修一下我的车吧!但是,维修工告诉我没有现在空闲,等有空闲了我可以上门服务!我告诉维修工如果你有空了那么你就直接来我家给我修理吧. 换成程序而言: 如果我想让一个类,调用我自己声明的方法,那么我需要一个一个回调接口来让我自己的类去实现它.通过这样来实现回调函数.回调函数就好像是C#中的委托.Java中并没有类似的机制.可以利用接口来实现回调. 下面是一个小的Demo: 下面是一个简单的类

java回调函数机制

Java回调函数机制 参考了网上的一些资料,下面也做出一些总结,供初学者了解学习. 一. 概述 软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用.回调.异步调用 . 同步调用:一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用: 回调:一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口: 异步调用:一种类似消息或事件的机制,解决了同步阻塞的问题,它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户

Android中回调函数的理解---本人Android纯新手

本人大二,刚刚接触Android,也刚刚申请的cnblog博客,说一下对Android中回调函数的理解,Android中回调函数和C++.JAVA中的默认构造函数差不多,即运行到了一定的代码时自动调用的代码,而Android中的回调函数和C++.JAVA中的默认构造函数的区别在于:C++.JAVA中的默认构造函数在创建一个对象时自动调用,而Android中的回调函数的自动调用是在比如按了HOME键之后.

Java回调函数详解

为了了解什么是回调函数,在网上查阅了如下资料,整理如下: 资料一: 首先说说什么叫回调函数? 在WINDOWS中,程序员想让系统DLL调用自己编写的一个方法,于是利用DLL当中回调函数(CALLBACK)的接口来编写程序,使它调用,这个就 称为回调.在调用接口时,需要严格的按照定义的参数和方法调用,并且需要处理函数的异步,否则会导致程序的崩溃. 这样的解释似乎还是比较难懂,这里举个简 单的例子: 程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序.程序员B要让a调用自己的程

一个简单的java回调函数的实现

回调函数 回调函数涉及的3个函数 登记回调函数 回调函数 响应回调函数 简单的解释 你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货.在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件.回答完毕.来自知乎点击打开链接 代码的实现 首先有一个接口 interface CallB

js回调函数(callback)理解

Mark! js学习 不喜欢js,但是喜欢jquery,不解释. 自学jquery的时候,看到一英文词(Callback),顿时背部隐隐冒冷汗.迅速google之,发现原来中文翻译成回调.也就是回调函数了.不懂啊,于是在google回调函数,发现网上的中文解释实在是太“深奥”了,我承认自己才疏学浅了.看了几个回调的例子后,貌似有点理解了.下面是我对回调函数的理解,要是理解错了,请指正,不甚感激. 首先还是从jquery网站上的英文定义入手,身为国人,我真感到悲剧.一个回调的定义被国内的“高手”解

Android(java)回调函数经典示例

回调函数经典示例 1.使用java回调函数来实现一个测试函数运行时间的工具类 public class TestObject { /** * 一个用来被测试的方法,进行了一个比较耗时的循环 */ public static void testMethod(){ for ( int i= 0 ; i< 100000000 ; i++){ } } /** * 一个简单的测试方法执行时间的方法 */ public void testTime(){ long begin = System.current