http://jiangzhengjun.iteye.com/blog/658354

动态语言的闭包是一个永恒的话题。闭包在编码过程的方便和快捷使得动态语言的拥护者对它津津乐道,而静态语言特别是Java语言的扇子们会拿出匿名内部类来说Java语言也有类似的功能。

JavaScript 中闭包的产生是由于 JavaScript 中允许内部 function,也就是在一个 function 内部声明的 function 。内部 function 可以访问外部 function 中的局部变量、传入的参数和其它内部 function 。当内部 function 可以在包含它的外部 function 之外被引用时,就形成了一个闭包。这个时候,即便外部 function 已经执行完成,该内部 function 仍然可以被执行,并且其中所用到的外部 function 的局部变量、传入的参数等仍然保留外部 function 执行结束时的值。下面是一个例子:

function Outer(){var i=0;function Inner(){alert(++i);}return Inner;
}
var inner = Outer();
inner();

因为函数Outer外的变量inner引用了函数Outer内的函数Inner,就是说:当函数Outer的内部函数Inner被函数Outer外的一个变量inner引用的时候,就创建了一个闭包。

闭包有什么作用:简而言之,闭包的作用就是在Outer执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回Outer所占用的资源,因为Outer的内部函数Inner的执行需要依赖Outer中的变量。

闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。通过这个定义,可以看出内部类是面向对象的闭包,因为它不仅包含创建内部类的作用域的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private成员。

C++有指针函数,可以实现回调。通过回调,对象能够携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象。Java中没有指针,回调是通过匿名类来实现的。

>>>回调的一种理解<<<

回调的基本原理跟好莱坞原则一样,Don't call me,I'll call you.

编程上来说,一般使用一个库或类时,是你主动调用人家的API,这个叫Call,有的时候这样不能满足需要,需要你注册(注入)你自己的程序(比如一个对象),然后让人家在合适的时候来调用你,这叫Callback。设计模式中的Observer就是例子:所有的观察者都需要向自己关心的主题Observable注册,然后主题在适当时机(主题类对象的属性发生变化时)通知所有订阅它的观察者并更新,其中观察者都实现了一个统一的Observer接口中的Update方法。

回调可以这样具体的想:

我提供一个方法,在另一个对象中注册,至于这个方法什么时候用,就要看这个对象怎么决定了,当这个对象调用这个方法时,就叫做回调

/**下面应用中ICallBack接口与Printer类好比是别人提供的API,*/
public interface ICallBack {//回调接口public void print();
}public class Printer {//API功能实现类ICallBack ic;void setCallBack(ICallBack ic) {this.ic = ic;}/* 供外界调用,即自己提供一个接口ICallBack,由外界PrintHandler去实现,再在适当时机回* 头调用外界所提供的实现print方法。我没有实现接口,但是我取得了一个实现接口的对象,而* 这个对象是外界类调用我的方法setCallBack()时所赋给我的,因此我可以在业务需要的地方* 来调用外界所提供的实现print方法*/void execute() {//... 固定算法 do some thingic.print(); //抽取变化的部分,由外界去实现//... 固定算法 do some thing}
}/**下面是外界应用*/
public class PrintHandler {public static void main(String[] args) {Printer printer = new Printer();/** 注意下面的这项代码片段,它给printer对象传递了一个实现ICallBack接口的匿名类,这* 样Printer类的对象就取得了一个实现回调接口的类,因此Printer可以在任何时候调用接* 口中的方法*/printer.setCallBack(new ICallBack() {/* * print 方法在PrintHandler类中实现,但不在PrintHandler 类对象中调用,而是* 在Printer类对象中调用,这就是回调*/public void print() {System.out.println("This is a callback");}});//  这句话可以设置成当满足某条件时再执行   printer.execute();}
}

>>>回调的另一种理解<<<

在以下Adjustable接口和Base类中都定义了adjust()方法,这两个方法的参数签名相同,但是有着不同的调节功能。

interface Adjustable {//功能:调节温度public void adjust(int temperature);
}class Base {private int speed;//功能:调节速度public void adjst(int spped) {this.speed = speed;}
}

可见虽然方法名同,但功能不同。

如果有一个Sub类同时具有调节温度和调节速度的功能,那么Sub类需要继承Base类,并实现Adjustable接口,但是以下代码并不能满足这一需求:

class Sub extends Base implements Adjustable {
private int temperature;

public void adjust(int temperature) {
this.temperature = temperature;
}
}

以上Sub类实现了Adjustable接口中的adjust()方法,并且把Base类中的adjust()方法覆盖了,这意味着Sub类仅仅有调节温度的功能,但失去了调节速度的功能。或以使用内部类来解决这一问题:

class Sub extends Base {private int temperature;// 调节温度的真真实现在外部内中,但不提供给外部,只能通过内部类回调private void adjustTemperature(int temperature) {this.temperature = temperature;}// 实现回调接口private class Closure implements Adjustable {public void adjust(int temperature) {// 通过回调外部类中的实现来完成温度调节功能adjustTemperature(temperature);}}// 获取回调节引用public Adjustable getCallBackReference() {return new Closure();}public static void main(String[] args) {Sub sub = new Sub();// 具有调节速度的功能sub.adjst(1);/**  回调: 又具有调节温度的功能*  客户类先调用sub实例的getCallBackReference()方法,获得*  内部类的Closure实例,然后再调用Closure实例的adjust()方*  法,该方法又调用Sub实例的adjustTemperature()方法。这种*  调用过程称为回调。*/sub.getCallBackReference().adjust(2);}
}

上面使Sub类既不覆盖Base类的adujst()方法,又实现了Adjustable接口的adjust()方法。

回调实质上是指一个类尽管实际上实现了某种功能,但是没有直接提供相应的接口,客户类可以通过这个类的内部类的接口来获得这种功能。而这个内部类本身并没有提供真正的实现,仅仅调用外部类的实现。可见,回调充分发挥了内部类所具有的访问外部类的实现细节的优势。

观察者模式也符合这一种理解:请参见XXXXXXXXXXXXX

内部类(闭包与回调)相关推荐

  1. (十)、java内部类与内部类的闭包和回调

    一.成员内部类 1.可以把一个内部类看做是一个成员.成员内部类可以无条件访问外部类的所有成员属性和成员方法. class OutterClass {//外部类private int in = 0;st ...

  2. boost::regex模块在 cpp 文件中搜索类定义,使用 C++ Builder 闭包作为回调的测试程序

    boost::regex模块在 cpp 文件中搜索类定义,使用 C++ Builder 闭包作为回调的测试程序 实现功能 C++实现代码 实现功能 boost::regex模块在 cpp 文件中搜索类 ...

  3. PHP闭包函数与闭包函数回调

    PHP闭包函数与闭包函数回调 没有名的函数成为匿名函数 eg: $sum = function($num1,$num2){return $num1+$num2; }; //匿名函数调用 echo $s ...

  4. java 闭包与回调

    闭包又称词法闭包 闭包最早定义为一种包含<环境成分>和<控制成分>的实体. 解释一:闭包是引用了自由变量的函数,这个被引用的变量将和这个函数一同存在. 解释二:闭包是函数和相关 ...

  5. 一文搞懂:词法作用域、动态作用域、回调函数、闭包

    把以前一直只限于知道,却不清晰理解的这几个概念完完整整地梳理了一番.内容参考自wiki页面,然后加上自己一些理解. 词法作用域和动态作用域 不管什么语言,我们总要学习作用域(或生命周期)的概念,比如常 ...

  6. [转载] java 内部类与闭包

    参考链接: Java本地内部类 内部类 首先,让我们看看什么是内部类(Java 内部类,成员类,局部类,匿名类等): 根据内部类的位置不同,可将内部类分为 成员内部类局部内部类 class C{ // ...

  7. 《java编程思想》学习笔记——内部类五

    2019独角兽企业重金招聘Python工程师标准>>> 10.5 在方法和作用域内的内部类 1.可以在一个方法里面或者任意的作用域内定义内部类.这么做有两个理由: (1)实现某类型的 ...

  8. Java 接口和抽象类可以被new么?——顺便总结内部类

    转载:https://blog.csdn.net/hackersaillen/article/details/47281549 背景: 最近有同事跟我说了他面试时遇到的问题,考官问:"接口和 ...

  9. thinking-in-java(10)内部类

    [0]开场白 1)内部类:将一个类的定义放在另一个类的定义内部,这个类就是内部类: 2)内部类优点:匿名内部类的一个优点就是可以将解决问题的代码隔离,聚拢在一点: [10.1]创建内部类 [荔枝]把类 ...

最新文章

  1. 循序渐进:带你理解什么是Java内存模型
  2. 如何在命令行下更改ip地址
  3. python判断哪个数最小_怎么用python比较三个数大小
  4. MCMC笔记Metropilis-Hastings算法(MH算法)
  5. 持续集成之“依赖管理”
  6. JZOJ 3600. 【CQOI2014】通配符匹配
  7. 依附B2B平台照样做搜索营销
  8. python 日志解决方案_日常Python问题的绝佳解决方案
  9. python入门指南txt-【杂谈】爬虫基础与快速入门指南
  10. 解决Manifest merger failed with multiple errors方法
  11. 抖音私信规则分析丨抖音企业号私信规则解读
  12. DQL -- 数据查询语言
  13. “数据结构”视频资料
  14. 【电子通识】烙铁使用方法
  15. 2022年G2电站锅炉司炉考试练习题及在线模拟考试
  16. String比较大小
  17. LoadRunner安装教程
  18. 2021年高光谱图像文献追踪_ISPRS_V.179_9
  19. nat123端口映射linux,nat123 linux版下载
  20. 群晖5.2php核心设置_求救!群晖dsm系统如何才能找到并设置php.ini文件

热门文章

  1. 五十八、2020美赛C题的思路以及个人Python的解法
  2. 八十五、Python | Leetcode数据结构之图和动态规划算法系列
  3. Map和hashmap
  4. 加法器 编码器 译码器 显示译码器
  5. 直播预告 | AAAI 2022论文解读:基于能量的主动域自适应学习方法
  6. 辰星计划2022 | 旷视研究院春季实习生招募开始啦!
  7. 浅谈数据中的偏差问题和推荐系统去偏最新研究进展
  8. 再谈对比学习:更好的对比样本选择,更好的对比效果
  9. 直播 | WWW 2021:用先验知识指导BERT注意力机制的语义文本匹配
  10. 【天池赛事】零基础入门语义分割-地表建筑物识别 Task6:分割模型模型集成