之是以将匿名内部類和回調函數兩個知識點一起寫,是因為最近學習zookeeper的時候正好遇到這麼一個例子。詳細内容請參考:https://www.w3cschool.cn/zookeeper/zookeeper_api.html
以下是與ZooKeeper集合連接配接的完整代碼。
public class ZooKeeperConnection {
// declare zookeeper instance to access ZooKeeper ensemble
private ZooKeeper zoo;
final CountDownLatch connectedSignal = new CountDownLatch(1);
// Method to connect zookeeper ensemble.
public ZooKeeper connect(String host) throws IOException,InterruptedException {
zoo = new ZooKeeper(host,5000,new Watcher() {
public void process(WatchedEvent we) {
if (we.getState() == KeeperState.SyncConnected) {
connectedSignal.countDown();
}
}
});
connectedSignal.await();
return zoo;
}
// Method to disconnect from zookeeper server
public void close() throws InterruptedException {
zoo.close();
}
}
匿名内部類的建立格式如下:
new 父類構造器(參數清單)|實作接口()
{
//匿名内部類的類體部分
}
在上面的代碼中,connect方法中在執行個體化ZooKeeper對象時用到了匿名内部類:
zoo = new ZooKeeper(host,5000,new Watcher() {
public void process(WatchedEvent we) {
if (we.getState() == KeeperState.SyncConnected) {
connectedSignal.countDown();
}
}
});
這個内部類沒有自己的名字,而是用到了Watcher接口,而通常情況下接口是不能用new的,但是在匿名内部類中可以這樣。匿名内部類的類體是一個名為process的方法,這個方法就是用來實作Watcher接口中定義的process抽象方法的。
在這個匿名内部類中恰好又運用了回調函數(又叫回調方法)。
回調是一種常見的程式設計模式。
在這種模式中,可以指出某個特定事件發生時應該采取的動作。ZooKeeper類通過其構造函數提供connect功能。構造函數的簽名如下 :
ZooKeeper(String connectionString, int sessionTimeout, Watcher watcher)
在上面的類ZooKeeperConnection中,connect 方法建立一個ZooKeeper對象,連接配接到ZooKeeper集合,然後傳回對象。
在此處使用CountDownLatch,就是為了形成一個回調函數。一開始将CountDownLatch對象connectedSignal值設為CountDownLatch(1);如果匿名内部類中的if語句不為真,這意味着下面的主線程會在一直處于等待狀态,停留在connectedSignal.await();處。這個就恰好符合了回調函數的意義:
在某個特定事件發生時應該采取的動作。 如果用戶端與Zookeeper沒有成功建立連接配接(也就是if語句不為真),就不傳回ZooKeeper對象zoo(在 connectedSignal.await()停留)。而一旦成功建立連接配接 (也就是if語句為真,執行connectedSignal.countDown()) ,就傳回 ZooKeeper對象zoo ( connectedSignal.await()放行)将匿名内部類改為普通類
在上述代碼中可以将匿名内部類拆出來,作為一個單獨類:XyzWatcher
public class XyzWatcher implements Watcher {
@Override
public void process(WatchedEvent watchedEvent) {
final CountDownLatch connectedSignal = new CountDownLatch(1);
if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
connectedSignal.countDown();
}
try {
connectedSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
原來的類ZooKeeperConnection改為如下:
public class ZooKeeperConnection {
// declare zookeeper instance to access ZooKeeper ensemble
private ZooKeeper zoo;
//public final CountDownLatch connectedSignal = new CountDownLatch(1);
// Method to connect zookeeper ensemble.
XyzWatcher xyz = new XyzWatcher();
public ZooKeeper connect(String host) throws IOException,InterruptedException {
zoo = new ZooKeeper(host,5000,xyz);
return zoo;
}
// Method to disconnect from zookeeper server
public void close() throws InterruptedException {
zoo.close();
}
}