Java回调函数

Java中回调是什么

Java函数回调,也许说的这么专业你并不知道它是干嘛,有啥用。实际上你都有用过,比如多线程的Thread接口就是最典型的例子,当你调用start()函数时,就会触发run()函数。

💡回调就是:A调用B,让 B 取处理某件事,然后 A 去忙其他的事情,B 处理完成之后再调用 A ,告诉 A 事情处理的结果

调用

  • 同步调用:同一时间只能做一件事
  • 异步调用:同一时间可以做多件事,一般通过以下两种手段实现:
    • 多线程:为需要阻塞的方法单独启动一个线程执行
    • 回调:执行完成后通过回调,通知主线程执行完毕或者获取执行结果

java 回调

1️⃣基本回调

A <--> B

A对象 ----B.fb(A) -----> B对象 // 调用B的fb()时传入A本身(this)

B对象(fb 方法)----->A.fa()------>A对象 // B就可以直接调用A,fa()就是回调方法

2️⃣接口回调

基于接口回调:若只能给fb()传入A类型那么就是强耦合,所以一般给 fb() 传入的是一个接口,A实现这个接口

A <--> B

AImpl ----B.fb(IA) -----> B对象 // IA是接口,AImpl是IA的实现类

B对象(fb 方法)------>IA.fa()----->AImpl

3️⃣异步回调

异步回调就是给B.fb()方法单独起一个线程去执行

  • 使用场景:当A要调用B的某个方法,且该方法会产生阻塞,或耗时较长,则可以将该方法做成异步调用
  • 异步通信:通过回调机制进行通信,执行完后告知A

AImpl ----B.fb(IA) -----> B对象 // B.fb(IA)单独起一个线程执行

B对象(fb 方法)------>IA.fa()----->AImpl

代码

概念说完了,下面就上代码...

同步调用

码农(Programmer)现在需要做几件事情:

  1. 敲代码一整天(敲代码)
  2. 将今天工作代码上传到Github上(上传代码)
  3. 备注一下完成日期(记录下完成的日期)

下面我们用程序去实现:程序一共就三个类:

  • Programmer(码农类)
  • Github(Github类 用于保存码农提交的代码)
  • TestDemo(用于测试并显示结果)

如下所示:

public class Programmer {

    public void code(){                       
        System.out.println("coding");      //step1.写代码
        new Github().push();               //step2.提交代码 
        recordToday();                     //step3. 记录的日期
    }

    public void recordToday(){
        System.out.println("i'm done " + new Date());
    }
}
// 只负责上传代码
public class Github {
    public void push(){
        System.out.println("git push");
    }
}
// 让Programmer工作
public class TestDemo {
    public static void main(String args[]){
        Programmer p = new Programmer();
        p.code();
    }
}

执行结果如下:

基本回调

可否给苦逼程序员一条生路,让他提交代码之后就下班,像记录日期:recodeToday()这种事让Github类去负责。

换句话说,Github类的push()函数执行完后,Github类去调用Programmer类的recodeToday()方法,而不是Programmer自己去调用,略微改动后

// A
public class Programmer {
    public void code(){
        System.out.println("coding");
        new Github().push(this);   // B.fb(this)
        // 这里没有 step3,码农没有自己调用 recordToday()方法.
    }

    // A.fa(),回调方法
    public void recordToday(){
        System.out.println("i'm done " + new Date());
    }
}
// B
public class Github {
    public void push(Programmer p ){   // push的参数多了Programmer类
        System.out.println("git push");
        p.recordToday();    // 执行回调
    }
}

最后执行结果不变

接口回调(可以结合 lambda)

如果现在不只有Programmer了还有Teacher和Student,那GitHub的push方法难道要再重载?最好的办法是push依赖接口

// IA,回调接口
public interface RecodeInterface {
    public void recode();
}
// B
public class Github {
    public void push(RecodeInterface r ){ // 依赖接口
        System.out.println("git push");
        r.recode(); // A.fa(),执行回调
    }
}
// AImpl,实现了接口
public class Programmer implements RecodeInterface{
    public void code(){
        System.out.println("coding");
        new Github().push(this); // B.fb(A)
    }

    @Override
    public void recode() { // 回调函数
        System.out.println("Programmer done " + new Date());
    }
}
public class Student {
    public void code(){
        System.out.println("coding");
        new Github().push(new StudentRecodeToday());
    }

    // AImpl,也可以单独抽象出一个内部类
    public class StudentRecodeToday implements RecodeInterface{
        @Override
        public void recode() {
            System.out.println("Student done "+ new Date());
        }
    }
}

✅使用 lambda 表达式

public class Student {
    public void code() {
        System.out.println("coding");
        new Github().push(() -> System.out.println("Student done " + new Date()));
    }

    // AImpl,也可以单独抽象出一个内部类
//    public class StudentRecodeToday implements RecodeInterface{
//        @Override
//        public void recode() {
//            System.out.println("Student done "+ new Date());
//        }
//    }
}

异步回调

// IA,回调接口
public interface mycallback {
    void onData(Object message); // 正常处理
    void onError(Exception e); // 异常处理
}
// AImpl,实现了回到接口
public class Client implements mycallback{
    int count=0;
    @Override
    public void onData(Object message) {
        count++;
        System.out.println("received message:"+message.toString());
    }

    @Override
    public void onError(Exception e) {
        System.out.println("error!");
    }
    public void send(String message){
        // 异步回调核心!!! 为B.fb(IA)单独启动一个线程
        Thread thread=new Thread(new Server(Client.this,message)); 
        thread.start();
    }
}
// B
public class Server implements Runnable{
    mycallback c;
    Object message;
    public Server(mycallback cl,Object o){
        c=cl;
        message=o;
    }
    @Override
    public void run() {
        try {
            c.onData(message+" after server"); // 执行回调
        }catch (Exception e){
            c.onError(e);
        }
    }
}

启动类

public class Work{

    public static void main(String[] args){
        Client c1=new Client();
        c1.send(hello);
        System.out.println("do others...");
    }
}

结果

do others...
received message:hello
posted @   kk小新  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示