Home  >  Article  >  Java  >  Detailed explanation of Java’s callback mechanism

Detailed explanation of Java’s callback mechanism

高洛峰
高洛峰Original
2017-01-24 11:52:351340browse

There is always a certain interface between modules. From the perspective of calling methods, they can be divided into three categories: synchronous calls, callbacks and asynchronous calls. The following focuses on the callback mechanism in detail.

1. Overview

The callback mechanism in Java is a relatively common mechanism, but it may be used less in your program. In some large programs Callback mechanisms can be found everywhere in the framework. This article will slowly approach Java's callback mechanism through some specific examples.

2. Callback

The so-called callback: Class A calls a method C in class B, and then class B in turn calls a method in class A. D, this method D is called the callback method. In actual use, there will be different callback forms, such as the following.

2.1 Synchronous callback

Here I assume such a situation.

Director B of company A told his subordinate (project manager C) that he wanted to do a survey, but he didn’t need C to do it himself. You can ask manager C to arrange for programmer D below him to complete it. Manager C found programmer D and told him that he now had to complete a research task. And tell manager C the results of the survey. If there are any problems, you still have to continue. Because here C asks D to do something, and then D still has to communicate the result with C. This is the callback model. The following is a class diagram of a general callback:

Detailed explanation of Java’s callback mechanism

##First we need to have a callback interface CallbackInterface


CallbackInterface.java

public interface CallbackInterface {
  public boolean check(int result);
}


In the background, programmer D wants to communicate the results with project manager C, so the project manager here needs to implement the above callback interface:


Manager.java

public class Manager implements CallbackInterface {
 
  private Programmer programmer = null;
 
  public Manager(Programmer _programmer) {
    this.programmer = _programmer;
  }
 
  /**
   * 用于 Boss 下达的委托
   */
  public void entrust() {
    arrange();
  }
 
  // 进行安排下属进行 study 工作
  private void arrange() {
    System.out.println("Manager 正在为 Programmer 安排工作");
    programmer.study(Manager.this);
    System.out.println("为 Programmer 安排工作已经完成,Manager 做其他的事情去了。");
  }
 
  @Override
  public boolean check(int result) {
    if (result == 5) {
      return true;
    }
    return false;
  }
 
}


For programmer D, he needs to hold a reference to manager C in order to communicate with him. However, this is a task that Director B asked Manager C to arrange. In other words, other managers can also be allowed here, such as managers B1, B2, etc. Because the managers have implemented the callback interface, programmer D can directly hold this interface. As follows:


Programmer.java

public class Programmer {
 
  public void study(CallbackInterface callback) {
    int result = 0;
    do {
      result++;
      System.out.println("第 " + result + " 次研究的结果");
    } while (!callback.check(result));
 
    System.out.println("调研任务结束");
  }
}

It is simpler and clearer for the director, because this is equivalent to a Client test:


Boss.java

public class Boss {
 
  public static void main(String[] args) {
    Manager manager = new Manager(new Programmer());
    manager.entrust();
  }
}

Running results:


Manager is arranging work for Programmer

Results of the 1st study
Results of the 2nd study
Results of the 3rd study
Results of the 4th study
Results of the 5th study
End of research task
Arrangement work for Programmer has been completed, Manager Went to do other things.

2.2 Asynchronous callback

Still with the above example, your project manager cannot always wait for the results of your research. But after giving this task to you, he will not care about it. He will do his thing and you will do yours. Therefore, the callback function needs to be processed asynchronously.

So, here we need to modify the code of the Programmer class as follows:

Programmer.java

public class Programmer {
 
  public Programmer() {
  }
 
  public void study(CallbackInterface callback) {
    new StudyThread(callback).start();
  }
 
  // --------------------------- Programmer 正在做的工作 ---------------------------
 
  class StudyThread extends Thread {
 
    CallbackInterface callback = null;
 
    public StudyThread(CallbackInterface _callback) {
      callback = _callback;
    }
 
    @Override
    public void run() {
      int result = 0;
      do {
        result++;
        System.out.println("第 " + result + " 次研究的结果");
      } while (!callback.check(result));
 
      System.out.println("调研任务结束");
    }
  }
}

Running results :

Manager is arranging work for Programmer

Arranging work for Programmer has been completed, and Manager has gone to do other things.
Results of the 1st study
Results of the 2nd study
Results of the 3rd study
Results of the 4th study
Results of the 5th study
Research tasks End

2.3 Closures and callbacks

A closure is a callable object that records some information from the scope in which it was created.

2.3.1 Normal call

First, we can see how the call is performed under normal circumstances.

Incrementable.java

interface Incrementable {
  void increment();
}

This is an ordinary interface (in ordinary calls, it is just an ordinary interface, in callbacks, it is the callback interface, this should be easy to understand).

Callee1.java

class Callee1 implements Incrementable {
 
  private int i = 0;
 
  @Override
  public void increment() {
    i++;
    System.out.println(i);
  }
 
}

Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();
    callee1.increment();
  }
}

Callbacks is a test client class, not much to say , look directly at the code above.

2.3.2 Initial callback test

There is nothing to say about the above ordinary call, because for a normal Java programmer, it should be something that can be done without even thinking about it. .


Now if you want to form a callback, it is impossible to have only one callee (the callback object Callee1) based on the program structure or logical thinking. You also need a caller object. The caller can be written as follows:


Caller.java

class Caller {
 
  private Incrementable callbackReference;
 
  public Caller(Incrementable _callbackReference) {
    callbackReference = _callbackReference;
  }
 
  void go() {
    callbackReference.increment();
  }
}

Here Caller holds a reference to the callback interface callbackReference , as mentioned above, the programmer needs to hold a reference to the project manager, so that he can communicate with the project manager through this reference. The callbackReference here also plays this role.


Now let’s take a look at writing the test class:


Callbacks.java

public class Callbacks {
  public static void main(String[] args) {
    Callee1 callee1 = new Callee1();   
    Caller caller1 = new Caller(callee1);
    caller1.go();
  }
}

对于到目前为止的程序代码,完全可以对比上面项目经理安排程序员调研技术难题的代码。有异曲同工之妙。

2.3.3 闭包回调

相比于正常的回调,闭包回调的核心自然是在于闭包,也就是对作用域的控制。 
现在假设有一个用户(其他程序员)自定义了一个 MyInCrement 类,同时包含了一个 increment 的方法。如下:

class MyInCrement {
 
  public void increment() {
    System.out.println("MyCrement.increment");
  }
 
  static void f(MyInCrement increment) {
    increment.increment();
  }
}

另外有一个类 Callee2 继承自上面这个类:

class Callee2 extends MyInCrement {
 
  private int i = 0;
 
  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }
}

显而易见这里如果要调用 increment() 方法,就变成了一般的函数调用了。所以这里我们需要修改上面的 Callee2 类,修改的目标就是让 Callee2 类可以兼容 MyInCrement 类的 increment() 方法和 Incrementable 的 increment() 方法。修改后:

class Callee2 extends MyInCrement {
 
  private int i = 0;
 
  public void increment() {
    super.increment();
    i++;
    System.out.println(i);
  }
 
  private class Closure implements Incrementable {
 
    @Override
    public void increment() {
      Callee2.this.increment();
    }
  }
 
  Incrementable getCallbackReference() {
    return new Closure();
  }
}

注意,这里的 Closure 类是一个私有的类,这是一个闭包的要素。因为 Closure 类是私有的,那么就要有一个对外开放的接口,用来对 Closure 对象的操作,这里就是上面的 getCallbackReference() 方法。 Caller 类则没有改变。 
对于测试客户端就直接看代码吧:

public class Callbacks {
  public static void main(String[] args) {   
    Callee2 callee2 = new Callee2();
    Caller caller2 = new Caller(callee2.getCallbackReference());
    caller2.go();
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多Detailed explanation of Java’s callback mechanism相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn