Java回调函数(方法)

Java回调函数(方法)

引言

在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回调的写法

当我们使用回调函数时,可以使用以下写法:

  1. 直接
  2. 接口
  3. 匿名内部类
  4. Lambda表达式
  5. 方法引用
  6. 反射

在这些写法中,前两种较为常用。后面三种写法则更加灵活,但可能会影响代码的可读性和维护性,所以需要谨慎使用。

直接实现回调函数

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]:处理响应");
    }
}