除了内部类之外,java中还有其他方法可以实现回调吗?回调和闭包之间有什么区别?
答案 0 :(得分:10)
关闭是你如何构建它,回调就是你如何使用它。
回调可以实现为闭包(在具有它们的语言中)或接口的实现(在Java中,作为匿名内部类或常规类)。
回调意味着您将一段代码传递给一个函数,以便该函数可以稍后调用该段代码。这是一种特殊的参数。
这段代码可以是函数指针或闭包或具有众所周知方法的对象,具体取决于语言提供的内容。
答案 1 :(得分:5)
闭包和匿名内部类(以及其他)都可以用作回调。 callback只是一些代码,它作为参数传递给其他代码。
与Java的匿名内部类相比,闭包的一个重要区别在于(在命令式语言中)闭包可以修改周围范围的变量。 Wikipedia给出了以下示例:
var f, g;
function foo() {
var x = 0;
f = function() { return ++x; };
g = function() { return --x; };
x = 1;
alert('inside foo, call to f(): ' + f()); // "2"
}
foo();
alert('call to g(): ' + g()); // "1"
alert('call to f(): ' + f()); // "2"
答案 2 :(得分:1)
回调只是作为参数传递给其他代码的任何可执行代码。在频繁使用中,该可执行代码是一个闭包,但不一定。
关闭这个词有点滥用,许多人只是将它用作“匿名函数”的同义词,但至少according to Wikipedia,这是对该术语的误用。维基百科的文章解释得比我能做得更快。
答案 3 :(得分:1)
答案 4 :(得分:0)
我不这么认为。
如果有,那么它可能在某种程度上是劣等的,否则匿名的内部类将不会被广泛使用。
答案 5 :(得分:0)
没有区别。
可以将闭包定义为包含可以轻松执行的父上下文的代码块。
事实上,我之间唯一的区别就是写作的简易性。一个典型的groovy / ruby闭包确实比Java匿名类更小。
然而,考虑到像guava这样的Java框架,并且自由使用匿名类/接口,特别是对于典型的闭包,使用像filter这样的情况(与groovy的implementation比较),我可以说绝对没有设计差异。
答案 6 :(得分:0)
可悲的是,唯一合理的方式是内部/匿名课程。
您也可以使用反射来实现,但这通常更慢,更难维护(没有语法突出显示,很难在IDE中找到引用等)。一个例子:
myButton.addActionListener(EventHandler.create(ActionListener.class, handlerObject, "onClick"));
答案 7 :(得分:0)
现在,匿名类是处理Java中回调的最佳方法。然而,这可能会改变Java 7,它将实现闭包。 http://en.wikipedia.org/wiki/Closure_(computer_science)
答案 8 :(得分:0)
这是两个使用闭包和回调的实现。
这是一个更好的例子(可以在这里找到http://www.caglargonul.com/2013/04/10/is-it-really-a-closure-yes-it-is/)来理解闭包是什么。关键是
闭包带有引用环境而不仅仅是功能代码。
在Java 7及更低版本中实现闭包的最佳方法是使用接口。在此示例中,回调实现为闭包。
首先声明你的界面将保留你的闭包。
public interface CallBack {
void m(int e);
}
让我们添加一个负责保存闭包数组的类,两个用于添加和删除闭包的公共方法,以及一个在事件发生时调用闭包内函数的公共函数。
public class CCallBack {
List<CallBack> cbs = new ArrayList<>();
public void registerCallBack(CallBack f){
cbs.add(f);
}
public void removeCallBack(CallBack f){
if(cbs.contains(f)){
cbs.remove(f);
}
}
public void onAction(int i){
for (CallBack callBack : cbs) {
callBack.m(i);
}
}
}
这是神奇的部分。请参阅实际参考环境。
public class CallBackTester {
CCallBack cb = new CCallBack();
@Test
public void test_callback(){
CallBack cb1 = new CallBack() {
int x = 1;
@Override
public void m(int e) {
if(e==1){
System.out.println("You register this callback " + x + " time/times");
x++;
}
}
};
cb.registerCallBack(cb1);
cb.registerCallBack(cb1);
cb.registerCallBack(cb1);
cb.removeCallBack(cb1);
cb.onAction(1);
}
}
当我们声明cb1时,我们正在添加一个由变量x组成的引用环境。当我们在这个闭包中调用函数时,我们将这个变量递增一个。如果它是一个普通函数,当我们调用该函数时,x将被声明为1。但这不是一个正常的功能。这是一个关闭。所以每次我们在闭包中调用函数时都不会声明x。正如您在每次调用输出时所看到的那样,x正在递增。
You register this callback 1 time/times
You register this callback 2 time/times