There are always these certain interfaces 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 explaining 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, and callback mechanisms can be seen everywhere in some large frameworks. This article uses some specific examples to slowly get closer to the callback mechanism of Java.
2. Callback
The so-called callback: it means calling a method C in Class A in Class B, and then calling method D in Class A in Class B in Class B. This method D is called a callback method. When actually using it, there will be different callback forms, such as the following ones.
2.1 Synchronous callbacks
Here I assume such a situation.
Company A's director B told his subordinate (project manager C) that he wanted to do a survey, but C did not need to do it himself. Manager C can be asked to arrange for his programmer D to complete it. Manager C found programmer D and told him that a research task would be completed now. And tell the manager C the results of the survey. If there is any problem, you still have to continue. Because here is C asking D to do something, D still has to communicate the result with C after that. This is the callback model. The following is the general callback class diagram:
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 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; } /** * Used for the delegation issued by the boss*/ public void entrust() { arrangement(); } // Schedule subordinates to study work private void arrange() { System.out.println("Manager is arranging work for the Programmer"); programmer.study(Manager.this); System.out.println("The schedule of work for Programmer has been completed, and the Manager has gone to do other things."); } @Override public boolean check(int result) { if (result == 5) { return true; } return false; }} For programmer D, he needs to hold a quote from Manager C in order to communicate with him. However, here is the task that Director B asked Manager C to arrange. In other words, other managers can also be asked here, such as managers B1, B2, etc. Because the managers have implemented the callback interface, you can directly let programmer D hold this interface here. as follows:
Programmer.java
public class Programmer { public void study(CallbackInterface callback) { int result = 0; do { result++; System.out.println("Th" + result + "Result of the study"); } while (!callback.check(result)); System.out.println("Survey task ends"); }} It's even 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. The 5th Study. The scheduling work for Programmer has been completed. Manager has done other things.
2.2 Asynchronous callbacks
As for the example above, your project manager cannot always wait for the results of your research. But after you hand over this task to you, he will ignore it. He will do his own thing, you will do your own thing. Therefore, the callback function needs to be processed asynchronously here.
So, here we need to modify the code of the Programmer class, and modify it 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("Th" + result + "Result of the study"); } while (!callback.check(result)); System.out.println("Survey task ends"); } }}Running results:
Manager is scheduling work for Programmer The scheduling work for Programmer has been completed, and Manager is doing 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 The research task ended
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 made under normal circumstances.
Incrementable.java
interface Incrementable { void increment();}This is an ordinary interface (it is just a normal interface in ordinary calls, and it is a callback interface in a callback, which 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, there is nothing to say, just look at the above code.
2.3.2 Callback initial trial
There is nothing to say about the ordinary calls above, because for a normal Java programmer, this should be something that can be done without thinking.
Now if you want to form a callback, it is impossible to have only one callee (the callback object Callee1) in terms of the structure or logic of the program, and you also need a caller object. The caller can write it like this:
Caller.java
class Caller { private Incrementable callbackReference; public Caller(Incrementable _callbackReference) { callbackReference = _callbackReference; } void go() { callbackReference.increment(); }} Here Caller holds a callbackReference for a callback interface, just like the programmer mentioned above needs to hold a project manager's reference, so that you can communicate with the project manager through this reference. The callbackReference here also plays this role.
Now let's take a look at the writing of 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(); }}For the program code so far, we can completely compare the code above which the project manager arranges programmers to investigate technical problems. It has the same effect.
2.3.3 Closure callback
Compared with normal callbacks, the core of closure callbacks is naturally lying in closures, that is, control over the scope.
Now suppose that a user (other programmer) customizes a MyInCrement class and includes an increment method. as follows:
class MyInCrement { public void increment() { System.out.println("MyCrement.increment"); } static void f(MyInCrement increment) { increment.increment(); }}There is another class Callee2 inherited from the above class:
class Callee2 extends MyInCrement { private int i = 0; public void increment() { super.increment(); i++; System.out.println(i); }}It is obvious that if you want to call the increment() method here, it becomes a general function call. So here we need to modify the Callee2 class above. The goal of the modification is to make the Callee2 class compatible with the increment() method of the MyInCrement class and the increment() method of the Incrementable. After modification:
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(); }} Note that the Closure class here is a private class, which is an element of a closure. Because the Closure class is private, there must be an open interface for operations on Closure objects. This is the getCallbackReference() method above. The Caller class has not changed.
For testing clients, just look at the code:
public class Callbacks { public static void main(String[] args) { Callee2 callee2 = new Callee2(); Caller caller2 = new Caller(callee2.getCallbackReference()); caller2.go(); }}The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.