JAVA怎么实现回调


熟悉MS-Windows和X Windows事件驱动设计模式的开发人员,通常是把一个方法的指针传递给事件源,当某一事件发生时来调用这个方法(也称为“回调”)。Java的面向对象的模型目前不支持方法指针,似乎不能使用这种方便的机制。

Java支持interface,通过interface可以实现相同的回调。其诀窍就在于定义一个简单的interface,申明一个被希望回调的方法。


例如,假定当某一事件发生时会得到通知,我们可以定义一个interface:
public interface InterestingEvent {
    // 这只是一个普通的方法,可以接收参数、也可以返回值
    public void interestingEvent();
}

这样我们就有了任何一个实现了这个接口类对象的手柄grip。

当一事件发生时,需要通知实现InterestingEvent 接口的对象,并调用interestingEvent() 方法。
class EventNotifier {
    private InterestingEvent ie;
    private boolean somethingHappened;

    public EventNotifier(InterestingEvent event) {
        ie = event;
        somethingHappened = false;
    }

    public void doWork() {
        if (somethingHappened) {
            // 事件发生时,通过调用接口的这个方法来通知
            ie.interestingEvent();
        }        
    }
}

在这个例子中,用somethingHappened 来标志事件是否发生。

希望接收事件通知的类必须要实现InterestingEvent 接口,而且要把自己的引用传递给事件的通知者。
public class CallMe implements InterestingEvent {
    private EventNotifier en;

    public CallMe() {
        // 新建一个事件通知者对象,并把自己传递给它
        en = new EventNotifier(this);
    }

    // 实现事件发生时,实际处理事件的方法
    public void interestingEvent() {
        // 这个事件发生了,进行处理
    }
}

以上是通过一个非常简单的例子来说明Java中的回调的实现。

当然,也可以在事件管理或事件通知者类中,通过注册的方式来注册多个对此事件感兴趣的对象。

1. 定义一个接口InterestingEvent ,回调方法nterestingEvent(String event) 简单接收一个String 参数。

interface InterestingEvent {
    public void interestingEvent(String event);
}

 

2. 实现InterestingEvent接口,事件处理类

class CallMe implements InterestingEvent {
    private String name;
    public CallMe(String name){
        this.name = name;
    }    
    public void interestingEvent(String event) {
        System.out.println(name + ":[" +event  + "] happened");
    }
}

 

3. 事件管理者,或事件通知者

class EventNotifier {
    private List<CallMe> callMes = new ArrayList<CallMe>();
    
    public void regist(CallMe callMe){
        callMes.add(callMe);
    }
    
    public void doWork(){
        for(CallMe callMe: callMes) {
            callMe.interestingEvent("sample event");
        }
    }    
}

 

4. 测试

public class CallMeTest {
    public static void main(String[] args) {
        EventNotifier ren = new EventNotifier();
        CallMe a = new CallMe("CallMe A");
        CallMe b = new CallMe("CallMe B");

        // regiest
        ren.regist(a);
        ren.regist(b);
        
        // test
        ren.doWork();        
    }
}


转载于:https://my.oschina.net/u/1049180/blog/135790

<think>好的,我现在需要回答用户关于Java回调函数实现原理的问题。首先,我得回顾一下回调函数的基本概念。回调函数是一种常见的编程模式,允许在某个操作完成后执行特定的代码。在Java中,由于没有函数指针,通常通过接口来实现回调机制。 用户提供的引用中有几个例子,比如学生类的gotoschool方法,接受一个Callable接口的实例,并在某个操作后调用call方法。这说明Java回调的核心在于传递接口的实现类对象,然后在适当的时候调用接口中的方法。 接下来,我需要明确回调机制的工作流程。引用3提到,回调函数是调用者将函数指针传递给调用函数,这在Java中转化为传递接口实例。当某个事件发生时(比如异步操作完成),调用该接口的方法,从而触发回调逻辑。 另外,引用2中的例子展示了异步回调,通过启动新线程来执行耗时操作,这样不会阻塞主线程。这说明Java回调可以结合多线程实现异步处理,提高程序效率。 需要注意的是,Java回调与钩子函数的区别。引用3指出,钩子函数是在消息到达目标前捕获并处理,而回调函数是在特定操作完成后执行。这点需要明确区分,避免混淆。 现在需要组织这些信息,分步骤解释回调的原理和实现机制。首先介绍接口的作用,然后通过同步和异步回调的例子说明具体实现方式。同时,可以对比其他语言(如C/C++的函数指针)来帮助理解。 可能还需要提到匿名内部类或Lambda表达式(在Java 8+)简化回调实现,但用户提供的引用中没有涉及这些,所以暂时不深入,除非必要。 最后,确保回答结构清晰,逐步引导用户理解,并引用提供的资料来支持解释。同时,生成相关问题时要围绕回调机制的应用、异步实现、与其他概念的区别等方面。</think>### Java回调函数的实现原理及机制 #### 1. **回调函数的核心原理** Java回调函数的本质是通过**接口传递行为**,实现程序间的协作。其核心步骤如下: 1. **定义接口**:声明一个包含回调方法的接口,例如: ```java public interface Callable { void call(); } ``` 2. **调用方持有接口引用**:调用方(如`Student`类)通过参数接收接口的实现类对象: ```java public void gotoschool(int time, Callable callable) { // ...操作完成后调用回调 callable.call(); } ``` 3. **被调用方实现接口**:使用方(如其他类)实现该接口,定义具体的回调逻辑[^1]。 #### 2. **同步与异步回调的区别** - **同步回调**:直接在主线程中执行回调,会阻塞后续代码。 ```java callable.call(); // 直接调用,无异步处理 ``` - **异步回调**:通过多线程分离回调逻辑,避免阻塞主流程,如引用[2]中的示例: ```java new Thread(() -> A.work(classB.this)).start(); ``` 此时回调逻辑在子线程中执行,主线程可继续执行`System.out.println("classB:classA已经完成工作了")`[^2]。 #### 3. **回调与钩子函数的区别** - **回调函数**:由调用方主动触发,在**特定操作完成后**执行(如网络请求返回)。 - **钩子函数**:在**事件发生前拦截并处理**(如监听键盘输入),可修改或终止事件[^3]。 #### 4. **典型应用场景** 1. 事件驱动编程(如按钮点击事件)。 2. 异步任务通知(如文件下载完成回调)。 3. 框架扩展点(如Spring的`BeanPostProcessor`)。 #### 代码示例 ```java // 定义回调接口 interface PaymentCallback { void onSuccess(String msg); void onFailure(String error); } // 调用方 class PaymentService { void processPayment(PaymentCallback callback) { try { // 模拟支付操作 Thread.sleep(1000); callback.onSuccess("支付成功"); } catch (Exception e) { callback.onFailure("支付超时"); } } } // 使用方 public class Main { public static void main(String[] args) { new PaymentService().processPayment(new PaymentCallback() { @Override public void onSuccess(String msg) { System.out.println(msg); // 输出:支付成功 } @Override public void onFailure(String error) { System.err.println(error); } }); } } ``` 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值