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)现在需要做几件事情:
- 敲代码一整天(敲代码)
- 将今天工作代码上传到Github上(上传代码)
- 备注一下完成日期(记录下完成的日期)
下面我们用程序去实现:程序一共就三个类:
- 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)