https://blog.csdn.net/lixiangminghate/article/details/70189210html
之前老是對閉包(Closure)只知其一;不知其二的,最近花時間查閱資料,不少地方都講得語焉不詳,看後仍感受雲裏霧裏的。後來仍是研究了下李剛寫的《瘋狂Java講義》,裏面講得仍是比較清楚,才終於弄清楚了閉包是怎麼回事。如今分享研究結果出來,也算是給像我原來同樣有疑惑的學習者一個參考。程序員
閉包(Closure)是一種能被調用對象,它保存了建立它的做用域的信息。編程
Java並不能顯式地支持閉包,但對於非靜態內部類而言,它不只記錄了其外部類的詳細信息,還保留了一個建立非靜態內部類對象的引用,而且能夠直接調用外部類的private成員,所以能夠把非靜態內部類當成面向對象領域的閉包。閉包
經過這種仿閉包的非靜態內部類,能夠很方便地實現回調功能,回調就是某個方法一旦得到了內部類對象的引用後,就能夠在合適時候反過來調用外部類的方法。所謂回調,就是容許客戶類經過內部類引用來調用其外部類的方法,這是一種很是靈活的功能。學習
假設有下面的Teachable接口和Programmer基類,它們都提供了一個work方法,這兩個方法的方法簽名徹底相同,但方法功能可能不同。this
interface Teachableurl
{.net
void work();htm
}對象
public class Programmer
{
private String name;
//Programmer類的兩個構造器
public Programmer(){}
public Programmer(String name)
{
this.name = name;
}
//此處省略了name屬性的setter和getter方法
...
public void work()
{
System.out.println(name + "在燈下認真敲鍵盤...");
}
}
假設如今有一我的,既是一個程序員,也是一個教師。也就是說須要定義一個特殊的類,既須要實現Teachable接口,也須要繼承Programmer父類。表面上看起來這沒有任何問題,問題是Teachable接口和Programmer父類裏包含了相同的work方法,若是採用以下代碼來定義一個特殊的TeachableProgrammer類:
public class TeachableProgrammer extends Programmer implements Teachable
{
public void work()
{
System.out.println(super.name + "教師在講臺上講解...");
}
}
顯然上面的TeachableProgrammer類只有一個work方法,這個work方法只能進行「教學」,再也不能夠進行「編程」。但實際須要TeachableProgrammer類裏既包含「教學」的work方法,也包含「編程」的work方法。
這個時候,能夠經過一個仿閉包的內部類來實現這個功能:
public class TeachableProgrammer extends Programmer
{
public TeachableProgrammer(){}
public TeachableProgrammer(String name)
{
super(name);
}
//教學工做依然由TeachableProgrammer類定義
private void teach()
{
System.out.println(getName() + "教師在講臺上講解...");
}
private class Closure implements Teachable
{
public void work()
{
teach();
}
}
//返回一個非靜態內部類引用,容許外部類經過該非靜態內部類引用來回調外部類的方法
public Teachable getCallbackReference()
{
return new Closure();
}
}
上面的TeachableProgrammer只是Programmer類的子類,它能夠直接調用Programmer基類的work方法,該類也包含教學的teach方法,但這個方法與Teachable接口沒有任何關係,TeachableProgrammer也不能當成Teachable使用。此時建立了一個Closure內部類,它實現了Teachable接口,並實現了教學的work方法(粗體字部分)——但這種實現是經過回調TeachableProgrammer類的teach方法實現的。若是須要讓TeachableProgrammer對象進行教學,只需調用Closure內部類(它是Teachable接口的實現類)對象的work方法便可。
TeachableProgrammer類提供了一個獲取內部類對象的方法:該方法無需返回Closure類型,只需返回所實現接口:Teachable類型便可,由於它只須要當成一個Teachable對象使用便可。
下面圖1是上面三個類和一個接口的類圖:
圖1:類圖
圖1清楚地看出Closure內部類的做用,它可實現Teachable接口,也能夠當成Teachable使用,並且它是TeachableProgrammer的內部類,是回調TeachableProgrammer對象方法的入口,它的work方法實際上回調了TeachableProgrammer類的teach方法。
下面程序示範瞭如何讓TeachableProgrammer對象既執行「教學」的work方法,也執行「編程」的work方法。
public class TestTeachableProgrammer
{
public static void main(String[] args)
{
TeachableProgrammer tp = new TeachableProgrammer("李剛");
//直接調用TeachableProgrammer類從Programmer類繼承到的work方法
tp.work();
//表面上調用的是Closure的work方法,其實是回調TeachableProgrammer的teach方法
tp.getCallbackReference().work();
}
}
上面程序中粗體字部分,代表上調用了Teachable對象(其實是Closure對象)的work方法,實際回調了TeachableProgrammer對象的teach方法。內部類對象能夠很方便地回調其外部類的屬性、方法,這樣就可讓編程更加靈活。