这里写自定义目录标题
#CallBack
学习Java回调函数的心得
学习其实是一个先痛苦再快乐的过程,当我们在学习过程中遇到困难的时候,那是头皮发麻都想不出来的问题啊,但是一旦你做成功了,心里面就很要舒服啊,所以大家在学习的过程中就不要像我一样偷懒了。
什么是回调
刚开始听到这个词的时候,一头雾水,满脑壳都是包,想着没怎么听过可能也不怎么用吧,但是这后面发现不对劲,怎么到都在强调回调这个词,这不去了解不行啊,所以自己去网上查资料了解了回调的基本原理和操作,此博客仅给入门级同学看,如果有哪里理解有误的地方,请大牛马上把我Q出来骂一顿,给我纠正下。
回调:通俗易懂地讲,回调顾名思义就是“你调用我,我反过来又调用你”,例如 在Class A
中我调用了Class B
的一个方法,并且把A
的对象一起传给了 B
的这个方法,而B
的这个方法通过A的对象又调用了A
中的一个方法,A
的这个方法就成为回调方法或者回调函数。怎么样是不是感觉有点懵啊,下面我们用具体代码演示上面的操作:
**public class A {
private B b;
public void set(B b){
this.b = b;
System.out.println("我是A,我通过set方法调用了B的doSth方法");
//调用B中的方法doSth()
doit();
}
public void doit(){
b.doSth();
}
}
public class B {
//定义一个A类型的变量,用于 接收传入的形参A
private A a;
public B(A a){
this.a = a;
}
public void dothat(){
//把我的引用传给A
System.out.println("我是B,我通过dothat方法调用A的set()方法");
a.set(this);
}
public void doSth(){
System.out.println("我是doSth()方法");
}
}
//测试一下
public class test {
public static void main(String[] args){
A a = new A();
B b = new B(a);
//dothat里面调用A 的set方法,将b的自身引用传给a
b.dothat();
//set方法利用b的引用调用b的doSth方法,完成回调
}
}**
从上面的代码中,我们可以看到,B调用了A的set()方法,set()方法又调用了B的doSth方法,简单地完成了回调机制。
同步回调
和异步回调
,上面的实现方式就是同步实现的,同步和异步的区别在于:同步情况下,调用方要等被调用方处理完请求时才能完成其他任务。举个简单例子:就比如比当你写代码遇到Bug,怎么也调不出来时,你突然想到你们班有个大佬,于是给他打电话求助,当你向他发出求助请求时,他觉得这道题也比较难,一时半会儿解不出来,然后他说先把电话挂了,我想出来了给你回电话。
上述的事件中,如果采用同步调用,那么你就在你朋友想出问题之前什么是也干不了,因为你必须一直听着电话,他没想出来的话你只能一直等。而如果采用异步,也就是先把电话挂了,不管他多久能解决问题,你先忙你自己的事情,当然你还可以去问别的大佬,当他把问题解决了,再打电话通知你,这样你就不用一直等待了。那么异步回调关键是什么呢,就是你每次发送请求的时候都重新为这个请求创建了独立的新线程,从而实现异步。
讲了这么多大家基本懂了回调思想,但是可能还是一头雾水,回调有啥子用,为什么要学?
再给大家一个例子
服务端:具有计算两个数相加功能
客户端:像服务端发送请求,得到计算结果
大家知道客户端是有很多个的,不同的客户要求计算的数据也不一样,所以每次传到服务端的实例可能是不同的对象,就像上面的A
类中的set(B b)方法,他只能传入B
类型的引用,由于我的客户有可能是商人、学生、会计等等,所以这种设计显然不行,那我该怎么做呢,大家肯定会想到接口了,对的,我们用接口定义处理业务的方法,然后让每个客户根据自己的需求去实现接口中的方法即可,所以B
中的set(B b)可改为:set(interface A);
下面我再写一个例子帮助大家理解:
下面上代码:
客户端:
**public class Clienter {
private Service service;
private int a;
private int b;
private String request;
public Clienter(Service service,int a,int b){
this.a = a;
this.b = b;
this.service = service;
this.request = "请问"+this.a+"+"+this.b+"=?";
}
public void sendRequest(){
//启动新线程,实现异步功能
new Thread(new Runnable(){
public void run(){
try{
System.out.println("已经向客户端发送了问题请求......");
//调用service的getRequest方法处理客户端发送的请求,并且返回计算结果
service.getRequest(new myCallback(),request,a,b);
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
//客户端根据自己的需求来具体实现接口,不同的客户有不同要求
public class myCallback implements Callback{
public void doJob(int result){
//显示服务器端计算的结果
System.out.println("服务器处理完毕,处理结果是:"+a+"+"+b+"="+result);
}
}
}**
服务器端:
**public class Service {
private Callback callback;
public void getRequest(Callback callback,String request,int a,int b){
this.callback = callback;
System.out.println("客户单发请求:"+request);
System.out.println("正在处理......");
//沉睡两秒钟,用于计算思考
try{
Thread.sleep(2000);
//处理逻辑业务
int result = a + b;
//调用客户端的doJob将计算结果返回给客户端
this.callback.doJob(result);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}**
测试一下:
**public class DemoTest {
public static void main(String[] args){
Service service = new Service();
//初始化客户端,并将service的引用传进来,方便调用它的getRequest()方法,处理结果后再调用客户端的方法
Clienter clienter = new Clienter(service,899,13849);
//调用客户端的sendRequest方法,向客户端发送消息
clienter.sendRequest();
}
}**
上面这个客户端和服务端的通信充分体现回调机制的用处,并且是异步调用,一般程序中同步调用用的比较少,因为他不涉及线程问题,比较简单,在异步调用中,可以利用锁机制实更加复杂的功能。
以上就是我关于java中的回调机制的理解,希望多少对大家有所帮助。