引言
在java的回调函数,以类A调用类B方法为例
在测试类main方法调用了类A中的send方法,send方法在执行完成之后,会执行类B中的callback()方法,这个callback方法就是回调函数,表明类B的b方法执行完成。
public class Test {
public static void main(String[] args) {
//创建A对象
A a = new A();
//创建B对象,回调函数所在类
B b = new B();
//调用A对象的send传入CallBack对象并在最后执行B对象的callback方法
a.send(b);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(B b) {
System.out.println("[A]:收到响应");
b.callback();
}
}
class B {
//回调函数
public void callback() {
System.out.println("[B]:处理响应");
}
}
回调函数的同步和异步
同步回调
调用函数时,程序会一直等待该函数执行完毕并返回结果,然后才能继续执行后面的代码。这种方式可以确保函数的执行顺序和结果的正确性,但也可能会导致程序在等待函数返回结果时出现阻塞,从而降低程序的性能。
案例
public class Test {
public static void main(String[] args) {
//创建A对象
A a = new A();
//创建B对象,回调函数所在类
B b = new B();
//调用A对象的send传入CallBack对象并在最后执行B对象的callback方法
a.send(b);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(B b) {
System.out.println("[A]:收到响应");
// 模拟执行某个耗时任务
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
b.callback();
System.out.println("[A]:回调函数执行完毕");
}
}
class B {
//回调函数
public void callback() {
System.out.println("[B]:处理响应");
}
}
因为程序会等待任务完成,所以耗时的任务尽量使用异步回调
异步回调
调用函数时,程序会立即返回,并在后台执行函数。函数执行完毕后,会通知主线程或调用另一个回调函数以返回结果。这种方式可以提高程序的并发性和响应性,但也需要处理异步执行带来的复杂性和线程安全问题。
案例
public class Test {
public static void main(String[] args) {
//创建A对象
A a = new A();
//创建B对象,回调函数所在类
B b = new B();
//调用A对象的send传入CallBack对象并在最后执行B对象的callback方法
a.send(b);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(B b) {
System.out.println("[A]:收到响应");
ExecutorService executor = Executors.newSingleThreadExecutor();
// 异步执行任务
executor.execute(new Runnable() {
@Override
public void run() {
// 模拟执行某个耗时任务
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 回调B对象的callback方法
b.callback();
System.out.println("[A]:回调函数执行完毕");
}
});
executor.shutdown();
}
}
class B {
//回调函数
public void callback() {
System.out.println("[B]:处理响应");
}
}
这个例子中,创建一个新的线程来执行任务,并在任务完成后调用回调函数。
由于是异步回调,所以程序不会等待任务完成,而是在线程开始执行后立即返回。
在任务(线程中)执行期间,程序可以继续执行后面的代码
Java回调的写法
当我们使用回调函数时,可以使用以下写法:
- 直接
- 接口
- 匿名内部类
- Lambda表达式
- 方法引用
- 反射
在这些写法中,前两种较为常用。后面三种写法则更加灵活,但可能会影响代码的可读性和维护性,所以需要谨慎使用。
直接实现回调函数
public class Test {
public static void main(String[] args) {
//创建A对象
A a = new A();
//创建B对象,回调函数所在类
B b = new B();
//调用A对象的send传入CallBack对象并在最后执行B对象的callback方法
a.send(b);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(B b) {
System.out.println("[A]:收到响应");
b.callback();
}
}
class B {
//回调函数
public void callback() {
System.out.println("[B]:处理响应");
}
}
接口实现回调
public class Test {
public static void main(String[] args) {
//创建A对象
A a = new A();
//创建B对象,回调函数所在类
B b = new B();
//将B对象实例传递给A对象的send方法,并将回调函数接口传递给B对象
a.send(b::callback);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(CallBack callBack) {
System.out.println("[A]:收到响应");
callBack.call();
}
}
interface CallBack {
//回调函数接口
void call();
}
class B implements CallBack {
//实现回调函数接口
@Override
public void call() {
System.out.println("[B]:处理响应");
}
}
匿名类实现回调
public class Test {
public static void main(String[] args) {
// 创建A对象
A a = new A();
// 匿名类实现回调函数
Callback callback = new Callback() {
@Override
public void handleResponse() {
System.out.println("[B]:处理响应");
}
};
// 调用A对象的send传入CallBack对象并在最后执行回调函数
a.send(callback);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(Callback callback) {
System.out.println("[A]:收到响应");
// 执行回调函数
callback.handleResponse();
}
}
interface Callback {
// 回调函数
void handleResponse();
}
Lambda表达式实现回调
public class Test {
public static void main(String[] args) {
// 创建A对象
A a = new A();
// 匿名类实现回调函数
Callback callback = ()-> System.out.println("[B]:处理响应");
// 调用A对象的send传入CallBack对象并在最后执行回调函数
a.send(callback);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(Callback callback) {
System.out.println("[A]:收到响应");
// 执行回调函数
callback.handleResponse();
}
}
interface Callback {
// 回调函数
void handleResponse();
}
方法引用实现回调函数
public class Test {
public static void main(String[] args) {
// 创建A对象
A a = new A();
// 调用A对象的send方法并传递回调函数
a.send(B::callback);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(Callback callback) {
System.out.println("[A]:收到响应");
callback.onComplete();
}
}
class B {
// 回调函数
public static void callback() {
System.out.println("[B]:处理响应");
}
}
interface Callback {
void onComplete();
}
在上面的代码中,B::callback
表示 B 类的 callback
方法作为回调函数,使用函数式接口 Callback
将回调函数传递给 A 类的 send
方法,在 send
方法中通过调用回调函数的 onComplete
方法来触发回调函数的执行,从而实现了回调函数的功能。
反射实现回调函数
public class Test {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
//创建A对象
A a = new A();
//创建B对象,回调函数所在类
B b = new B();
//获取回调函数callback的Method对象
Method callback = B.class.getMethod("callback");
//调用A对象的send传入CallBack对象并在最后执行B对象的callback方法
a.send(b, callback);
System.out.println("[Main]:请求发完了,我去干点别的");
}
}
class A {
public void send(B b, Method callback) throws InvocationTargetException, IllegalAccessException {
System.out.println("[A]:收到响应");
//通过反射调用B对象的callback方法
callback.invoke(b);
}
}
class B {
//回调函数
public void callback() {
System.out.println("[B]:处理响应");
}
}