java的回調(diào)很有意思,是通過內(nèi)部類實(shí)現(xiàn)的。下面我們來看看Think in JAVA 上提供的有趣例子。
public class Callee1 implements Incrementable {
private int i = 0;
@Override
public void increment() {
i++;
System.out.println(i);
}
}
↓↓↓
外圍類繼承了MyIncrement ,MyIncrement 類中有一個(gè)increment()方法。
這里故意設(shè)置外圍類有一個(gè)increment()方法,因?yàn)閮?nèi)部類也有一個(gè)increment()方法。
作者的意思是想說內(nèi)部類的方法可以與外圍類的方法重名,且互相沒有影響。
甚至可以有多個(gè)內(nèi)部類,每個(gè)內(nèi)部類都可以有一個(gè)同名的方法。
這樣就可以同名的方法,但行為不同。
↓↓↓
class MyIncrement { //MyIncrement 類中有一個(gè)increment()方法
public void increment(){System.out.println("Other operation");}
static void f(MyIncrement mi) {mi.increment();}
}
class Callee2 extends MyIncrement {//外圍類繼承了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 () { //內(nèi)部類提供一個(gè)方法,將自己的引用返回.
return new Closure();
}
}
↓↓↓
內(nèi)部類提供一個(gè)方法getCallbackReference ()將自己的引用返回,Caller類獲得內(nèi)部類Closure的引用。
Caller類在自己的方法go()中使用內(nèi)部類的引用,并通過引用調(diào)用內(nèi)部類的方法。
此過程就形成了回調(diào)。
這樣就可以在運(yùn)行時(shí)通過持有的內(nèi)部類Caller的引用,進(jìn)行運(yùn)行時(shí)調(diào)用。
↓↓↓
class Caller {
private Incrementable callbackReference;
Caller(Incrementable cbh) {callbackReference = cbh;}
void go() {callbackReference.increment();}
}
public class Callbacks {
public static void main(String[] args) {
Callee1 c1 = new Callee1();
Callee2 c2 = new Callee2();
MyIncrement.f(c2);
// Caller caller1 = new Caller(c1);
Caller caller2 = new Caller(c2.getCallbackReference());
//
// caller1.go();
// caller1.go();
caller2.go();
// caller2.go();
}
}
↓↓↓
書上還有一句話說的很有意思:無論誰獲得內(nèi)部類Closure 的引用作為參數(shù),都只能調(diào)用increment()方法,除此之外沒有其他功能。
因?yàn)閮?nèi)部類Closure 實(shí)現(xiàn)了接口Incrementable ,并且getCallbackReference()方法返回的也是Incrementable 類型。
↓↓↓
public interface Incrementable {
void increment();
}