0%

JAVA回调

什么是回调函数

在Java中,回调函数是指将一个函数作为参数传递给另一个函数,并在特定事件发生时被调用。这种机制允许我们在程序执行过程中动态地传递代码逻辑,以便在特定事件发生时执行。

在Java中,回调函数通常通过接口或抽象类来定义。定义回调函数的接口或抽象类中包含一个或多个方法,用于定义回调函数的行为。然后,我们可以创建实现该接口或抽象类的类,并将其实例作为参数传递给其他函数或对象。当特定事件发生时,调用者将调用回调函数的方法,从而执行我们定义的逻辑。

回调函数在许多情况下非常有用,特别是在事件处理、异步编程和GUI开发中。通过使用回调函数,我们可以实现灵活的程序设计,将代码的执行控制权交给调用者,以便根据需要执行特定的操作。

同步回调和异步回调

同步回调是指当调用者发起回调请求时,被调用者立即执行回调函数,并在回调函数执行完毕后返回结果给调用者。在同步回调中,调用者需要等待回调函数执行完毕才能继续执行后续的操作。同步回调适用于简单的操作或者需要立即获取结果的场景。

异步回调是指当调用者发起回调请求时,被调用者不会立即执行回调函数,而是在后台或其他线程中执行回调函数,并在执行完毕后通过回调机制通知调用者。在异步回调中,调用者不需要等待回调函数执行完毕,而是可以继续执行其他操作。异步回调适用于耗时的操作或者需要避免阻塞调用者的场景。

总结起来,同步回调是指立即执行回调函数并等待结果返回的方式,适用于简单操作或需要立即获取结果的场景;异步回调是指在后台执行回调函数并通过回调机制通知调用者的方式,适用于耗时操作或需要避免阻塞调用者的场景。

同步回调

匿名内部类的回调

在Java中,匿名内部类可以用作回调函数的实现方式。匿名内部类是一种没有显式命名的内部类,它可以直接在代码中定义并实例化。

public class CallbackExample {

public static void main(String[] args) {
// 创建一个回调接口的实例
Callback callback = new Callback() {
@Override
public void onCallback() {
System.out.println("回调函数被调用了!");
}
};
// 调用方法,并将回调接口的实例作为参数传递
performOperation(callback);
}


public static void performOperation(Callback callback) {
// 执行某些操作
System.out.println("执行操作...");
// 操作完成后调用回调函数
callback.onCallback();
}


// 定义一个回调接口
public interface Callback {
void onCallback();
}

}

LAMDA的回调

在Java中,Lambda表达式可以用作回调函数的实现方式。Lambda表达式是一种简洁的语法形式,用于表示一个匿名函数。

public class CallbackExample {

public static void main(String[] args) {
// 使用Lambda表达式作为回调函数
performOperation(() -> {
System.out.println("回调函数被调用了!");
});
}


public static void performOperation(Callback callback) {
// 执行某些操作
System.out.println("执行操作...");

// 操作完成后调用回调函数
callback.onCallback();
}


// 定义一个回调接口
public interface Callback {
void onCallback();
}
}

在上面的示例中,我们使用Lambda表达式作为回调函数。在performOperation()方法中,我们将回调函数作为参数传递,并在操作完成后调用回调函数。

Lambda表达式的语法形式为(参数列表) -> { 表达式或代码块 }。在示例中,Lambda表达式的参数列表为空,因为回调函数不需要任何参数。在Lambda表达式的代码块中,我们输出一条消息。
通过使用Lambda表达式,我们可以更加简洁地定义回调函数,避免了创建额外的类或接口的繁琐过程。Lambda表达式的使用使得回调函数的实现更加紧凑和易读。

需要注意的是,Lambda表达式只能用于函数式接口,即只有一个抽象方法的接口。在示例中,回调接口Callback正好满足这个条件,因此可以使用Lambda表达式作为回调函数。

异步回调

简单线程回调

public class AsyncCallbackExample {

public static void main(String[] args) {
performAsyncOperation(new Callback() {
@Override
public void onCallback(String result) {
System.out.println("异步操作完成,结果为:" + result);
}
});

System.out.println("主线程继续执行其他操作...");
}


public static void performAsyncOperation(Callback callback) {
// 创建一个新的线程执行异步操作
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 模拟异步操作
Thread.sleep(2000);

// 异步操作完成后调用回调函数
callback.onCallback("异步操作结果");
}
});

// 启动线程执行异步操作
thread.start();
}


// 定义一个回调接口
public interface Callback {
void onCallback(String result);
}
}

CompletableFuture中的回调

import java.util.concurrent.CompletableFuture;
public class CompletableFutureCallbackExample {

public static void main(String[] args) {
// 创建一个CompletableFuture对象,表示异步操作
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模拟异步操作
Thread.sleep(2000);

// 返回异步操作的结果
return "异步操作结果";
});

// 注册回调函数,处理异步操作的结果
future.thenAccept(result -> {
System.out.println("异步操作完成,结果为:" + result);
});

System.out.println("主线程继续执行其他操作...");

// 防止主线程执行完就退出了
future.join();
}
}

在上面的示例中,我们首先使用CompletableFuture.supplyAsync()方法创建了一个CompletableFuture对象,表示一个异步操作。在supplyAsync()方法中,我们传递一个Supplier函数式接口,用于执行异步操作并返回结果。

然后,我们使用thenAccept()方法注册了一个回调函数,用于处理异步操作的结果。在回调函数中,我们输出异步操作的结果。
在主线程中,我们继续执行其他操作。最后,我们使用join()方法阻塞主线程,等待异步操作完成。

通过使用CompletableFuture中的回调函数,我们可以更加方便地处理异步操作的结果。thenAccept()方法用于注册一个消费者回调函数,它接收异步操作的结果作为参数,并在异步操作完成后执行。我们可以在回调函数中处理异步操作的结果,例如输出、处理或传递给其他方法。

总结

  • 回调函数可以被同步执行,意味着它可以在其他操作执行后没有延迟地被立刻执行。
  • 回调函数可以是异步的,这意味着它可以在后台执行,并且可能需要一些时间才能执行
  • Observable设计模式使用回调来通知感兴趣的实体何时发生了操作。