天天看點

Thinking in java-30 Closure and Callback閉包和回調

1. What is callback and closure is?

Thinking in java 中的内部類章節中有關于‘閉包和回調’的内容,簡單做一下整理。這裡有關此問題的詳細stackoverflow上Q&A, 及在thinking in java上的筆記内容。

閉包:閉包是一種從它被建立的作用範圍内保留資訊的可以調用的對象。從該定義可以看出,内部類是一種面向對象的閉包,因為它不僅包含外部類對象的所有資訊(這就是所謂的它被建立出來的範圍),而且它還儲存整個外部類對象的引用,它有權限操作所有的成員(包括private 成員)。

回調:java中關于引入指針機制所引發的最大争議就是允許了所謂的–’callback’回調機制。 在回調過程中,一些資訊傳遞給其他的對象,并允許其在将來的某個時刻回調原本的對象。

2. A java demo adapted from ‘thinking in java’

這個例子挺長,為何選這個例子作為callback的demo呢?

首先,Caller提供的函數是以Increment接口為參數類型的,而Callee2并沒有顯式implement Increment接口,是以這裡通過了内部類的方式實作了這個機制。

package com.fqy.blog;

/*
 * A simple interface with a method increment().
 */
interface Incrementable {
    void increment();
}

/*
 * A simple class that implements interface Incrementable.
 */
class Callee1 implements Incrementable {
    private int i = ;

    @Override
    public void increment() {
        i++;
        System.out.println("In Callee1: " + i);
    }
}

/*
 * A new class with a method increment() and a static method f() which takes a
 * MyIncrement object as its parameter.
 * 
 */
class MyIncrement {
    void increment() {
        System.out.println("In MyIncrement: Other operation!");
    }

    static void f(MyIncrement mi) {
        mi.increment();
    }
}

/*
 * Another class that extends class MyIncrement, contains a method increment()
 * 
 */
class Callee2 extends MyIncrement {
    private int i = ;

    private void incr() {
        i++;
        System.out.println("In Callee2: " + i);
    }

    private class Closure implements Incrementable {
        @Override
        public void increment() {
            incr();
        }
    }

    Incrementable getCallbackReference() {
        return new Closure();
    }
}

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();
    }
}

//Running result:
In MyIncrement: Other operation!
In Callee1: 
In Callee1: 
In Callee2: 
In Callee2: 
           

3. 個人了解

  • closure閉包是我們如何build的方式,而callback是我們如何使用的方式。Closure is how you build it, callback is how you use it.
  • 回調callback可以通過閉包closure的方式實作,或者通過實作接口的方式。
  • 回調意味着,我們可以傳遞給一段代碼給一個函數,這個函數可以在将來某個時候調用那一段代碼。這是一種特殊的參數。

繼續閱讀