Java中的闭包与回调
作者:网络转载 发布时间:[ 2015/10/9 13:24:16 ] 推荐标签:测试开发技术 编程语言
看下面的例子:
packagecallbackexample;
publicinterfaceICallBack{
publicvoidpostExec();//需要回调的方法
}
另外的一个类:
packagecallbackexample;
publicclassFooBar{//组合聚合原则
privateICallBackcallBack;
publicvoidsetCallBack(ICallBackcallBack)
{this.callBack=callBack;doSth();}
publicvoiddoSth()
{callBack.postExec();}}
第二个类在测试类里面,是一个匿名类:
packagecallbackexample;
publicclassTest{
publicstaticvoidmain(String[]args)
{FooBarfoo=newFooBar();
foo.setCallBack(newICallBack(){
publicvoidpostExec()
{System.out.println("在Test类中实现但不能被Test的对象引用,而由FooBar对象调用");}});}}
以上代码中:
1.两个类:匿名类和FooBar
2.匿名类实现接口ICallBack(在test测试的main方法中用匿名类的形式实现)
3.FooBar拥有一个参数为ICallBack接口类型的函数setCallBack(ICallBacko)
4.匿名类运行时调用FooBar中setCallBack函数,以自身传入参数
5.FooBar已取得匿名类,可以随时回调匿名类中所实现的ICallBack接口中的方法
首先回调方法的概念与“构造方法”的概念是不一样的,它不是指java中某个具有特殊意义或用途的方法。
称它为方法的“回调”更恰当一些,它是指方法的一种调用方式。任何一个被“回调”的方法,皆可称之为“回调方法”
方法的回调通常发生在“java接口”和“抽象类”的使用过程中。
假设有接口名为ICallBack其中有方法名为postExec()
有类Myclass实现了该接口,也是一定实现了postExec()这个方法。现在有另一个类FooBar它有个方法setCallBack(ICallBackcallBack),并且setCallBack方法调用了callBack的postExec()方法。
如果现在,我们使用一个Myclass的实例myClass,将它作为参数带入到setCallBack(ICallBackcallBack)方法中,我们说setCallBack(ICallBackcallBack)方法回调了myClass的postExec()方法。
Java引人争议的问题之一是,人们认为Java应该包含某种类似指针的机制,以允许回调(callback)。通过回调,对象能够携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象。
如果回调是通过指针实现的,那么只能寄希望于程序员不会误用该指针。然而,您应该已经了解到,Java更小心仔细,所以没有在语言中包括指针。
通过内部类提供闭包的功能是优良的解决方案,它比指针更灵活、更安全。
再看下面的例子:
//innerclasses/Callbacks.java
//Usinginnerclassesforcallbacks
packageinnerclasses
interfaceIncrementable{
voidincrement();
}
//Verysimpletojustimplementtheinterface
classCallee1implementsIncrementable{
privateinti=0;
publicvoidincrement(){
i++;
System.out.println(i);
}
}
classMyIncrement{
publicvoidincrement(){System.out.println("Otheroperation");}
staticvoidf(MyIncrementmi){mi.increment();}
}
//Ifyourclassmustimplementincrement()in
//someotherway,youmustuseaninnerclass:
classCallee2extendsMyIncrement{
privateinti=0;
publicvoidincrement(){
super.increment();
i++;
System.out.println(i);
}
privateclassClosureimplementsIncrementable{
publicvoidincrement(){
//Specifyouter-classmethod,otherwise
//you'dgetaninfiniterecursion
Callee2.this.increment();
}
}
IncrementablegetCallbackReference(){
returnnewClosure();
}
}
classCaller{
privateIncrementablecallbackReference;
Caller(Incrementablecbh){callbackReference=cbh;}
voidgo(){callbackReference.increment();}
}
publicclassCallbacks{
publicstaticvoidmain(String[]args){
Callee1c1=newCallee1();
Callee2c2=newCallee2();
MyIncrement.f(c2);
Callercaller1=newCaller(c1);
Callercaller2=newCaller(c2.getCallbackReference());
caller1.go();
caller1.go();
caller2.go();
caller2.go();
}
}
输出:
Otheroperation
1
1
2
Otheroperation
2
Otheroperation
3
这个例子进一步展示了外围类实现一个接口与内部类实现此接口之间的区别。代码而言,Callee1是简单的解决方式。Callee2继承自MyIncrement,后者已经有了一个不同的increment()方法,并且与Incrementable接口期望的increment()方法完全不相关。
所以如果Callee2继承了MyIncrement,不能为了Incrementable的用途而覆盖increment()方法,于是只能使用内部类独立地实现Incrementable。还要注意,当创建了一个内部类时,并没有在外围类的接口中添加东西,也没有修改外围类的接口。
注意,在Callee2中除了getCallbackReference()以外,其他成员都是private的。要想建立与外部世界的任何连接,interfaceIncrementable都是必需的。在这里可以看到,interface是如何允许接口与接口的实现完全独立的。
内部类Closure实现了Incrementable,以提供一个返Callee2的“钩子”(hook)——而且是一个安全的钩子。无论谁获得此Incrementable的引用,都只能调用increment(),除此之外没有其他功能(不像指针那样,允许您做很多事情)。
Caller的构造器需要一个Incrementable的引用作为参数(虽然可以在任意时刻捕获回调引用),然后在以后的某个时刻,(Caller对象可以使用此引用回调Callee类。
回调的价值在于它的灵活性——可以在运行时动态地决定需要调用什么方法。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Java性能测试有哪些不为众人所知的原则?Java设计模式??装饰者模式谈谈Java中遍历Map的几种方法Java Web入门必知你需要理解的Java反射机制知识总结编写更好的Java单元测试的7个技巧编程常用的几种时间戳转换(java .net 数据库)适合Java开发者学习的Python入门教程Java webdriver如何获取浏览器新窗口中的元素?Java重写与重载(区别与用途)Java变量的分类与初始化JavaScript有这几种测试分类Java有哪四个核心技术?给 Java开发者的10个大数据工具和框架Java中几个常用设计模式汇总java生态圈常用技术框架、开源中间件,系统架构及经典案例等
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南