Java中的回调
Incrementable接口
package com.wangzw.test.unit11.test14;
/**
* @Author wangzw
* @Date 2021/4/22 20:08
*/
public interface Incrementable {
void increment();
}
MyIncrement类
package com.wangzw.test.unit11.test14;
/**
* @Author wangzw
* @Date 2021/4/22 20:09
*/
public class MyIncrement {
public void increment() {
System.out.println("Other operation");
}
public static void f(MyIncrement mi) {
mi.increment();
}
}
Callee1类
package com.wangzw.test.unit11.test14;
/**
* @Author wangzw
* @Date 2021/4/22 20:08
*/
public class Callee1 implements Incrementable {
private int i = 0;
@Override
public void increment() {
i++;
System.out.println(i);
}
}
Callee2类
package com.wangzw.test.unit11.test14;
/**
* @Author wangzw
* @Date 2021/4/22 20:10
*/
public class Callee2 extends MyIncrement {
private int i = 0;
@Override
public void increment() {
super.increment();
i++;
System.out.println(i);
}
private class Closure implements Incrementable {
@Override
public void increment() {
Callee2.this.increment();
}
}
public Incrementable getCallbackReference() {
return new Closure();
}
}
Caller类
package com.wangzw.test.unit11.test14;
/**
* @Author wangzw
* @Date 2021/4/22 20:13
*/
public class Caller {
private Incrementable callbackReference;
public Caller(Incrementable cbh) {
callbackReference = cbh;
}
public void go() {
callbackReference.increment();
}
}
Callbacks测试类
package com.wangzw.test.unit11.test14;
/**
* @Author wangzw
* @Date 2021/4/22 20:14
*/
public class Callbacks {
public static void main(String[] args) {
Callee1 c1 = new Callee1();
Callee2 c2 = new Callee2();
// 输出Other operation 输出1,此时c2中的i为1
MyIncrement.f(c2);
Caller caller1 = new Caller(c1);
Caller caller2 = new Caller(c2.getCallbackReference());
// 输出1,此时c1中的i为1
caller1.go();
// 输出2,此时c1中的i为2
caller1.go();
// 输出Other operation,输出2,此时c2中的i为2
caller2.go();
// 输出Other operation,输出3,此时c2中的i为3
caller2.go();
}
}
此例展示了外围类实现一个接口与内部类实现此接口之间的区别。就代码而言,Callee1是简单的解决方式。Callee2继承自MyIncrement,后者已经有了一个不同的increment()方法,并且与Incrementable接口期望的increment()方法完全不相关。所以如果Callee2继承了MyIncrement,就不能为了Incrementable的用途而覆盖increment()方法,于是只能使用内部类独立地实现Incrementable。还要注意,当创建一个内部类时,并没有在外围类的接口中添加东西,也没有修改外围类的接口。
注意,在Callee2中除了getCallbackReference()以外,其他成员都是private的。要想建立与外部世界的任何连接,interface Incrementable都是必须的。在这里可以看到,interface是如何允许接口与接口的实现完全独立的。
内部类Closure实现了Incrementable,以提供一个返回Callee2的“钩子”(hook)——而且是一个安全的钩子。无论谁获得此Incrementable的引用,都只能调用increment(),除此之外没有其他功能(不像指针那样,允许你做很多事情)。
Caller的构造器需要一个Incrementable的引用作为参数(虽然可以在任何时刻捕获回调引用),然后在以后的某个时刻,Caller对象可以使用此引用回调Callee类。
回调的价值在于它的灵活性——可以在运行时动态的决定需要调用什么方法。