我最近遇到了来自EclipseCon 2014的presentation,在第5页,他们说 &#34; Lambda表达式允许您将代码视为数据&#34; < / strong>即可。
我也遇到了这个示例代码
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("button clicked");
}
});
来自&#34; Java 8 Lambdas:实用功能编程&#34;理查德沃伯顿在那里他说
&#34;这实际上是使用代码作为数据的一个例子 - 我们给出了 按钮表示动作的对象。&#34;
代码作为数据对于Lambda表达式和/或匿名内部类是什么意思?
答案 0 :(得分:5)
当您将功能作为参数传递给另一个方法时,例如当有人单击像您的示例代码那样的按钮时应采取的操作。
Lambda表达式使您能够执行此操作,将功能视为方法参数 = code as data。
有关更多信息和lambda代码示例,请参阅oracle link。
答案 1 :(得分:3)
“代码作为数据”的概念与具有一等函数的编程语言的概念密切相关。有关此主题,请参阅Wikipedia article。在这篇other answer中我谈到Java是否具有一流的功能,但该文章也讨论了其他一些问题。
维基百科文章(引用Abelson&amp; Sussman,计算机程序的结构和解释,第1.3节)中的定义特别提到了使其成为“一流”的功能的以下特征:
这些都是您对数据所做的事情。如果你可以使用函数执行相同的操作,那就像将代码视为数据一样。
如果仔细研究如何将lambdas添加到Java编程语言中,您将看到lambda实际上已转换为功能接口的实例。因此,它是某个对象的实例,因此是类Object
的后代,并且与Java中的所有对象一样,它具有equals(), hashCode(), getClass()
等方法,并且可以将引用与{{1}进行比较等等。但是,明确不鼓励您依赖任何此类内容。有关其他讨论,请参阅我的other answer。实际上,当你在Java中使用lambdas时,感觉就像你将代码作为参数传递,或者将它分配给变量。例如,
==
你真的最终没有考虑到这样一个事实:在lambdas中,lambda是作为功能接口实例的对象。
答案 2 :(得分:1)
这意味着您编写的程序代码也是数据,可以作为参数传递给另一个method
并由程序操作。< / p>
答案 3 :(得分:1)
在Java的黄金时代,没有方便的范例将函数从调用者传递给接收者。你必须使用某种方法(通常通过&#34; Command&#34;设计模式)将一个类组合在一起,然后将其传递给接收者。
Java 8 Lambdas通过引入Lambda表达式改变了范式。忘记这些如何表示给运行时,Lambdas在开发人员看来是可以传递给方法的纯代码。代码作为数据!
这种范式转换为java.util.Stream提供了接受lambda表达式的方式,这些表达式告诉集合执行一项功能。
对于整个主题的清晰,简洁和完整的处理是Maurice Naftalin的新书Mastering Lambdas - Java Programming in a Multi-Core World。答案 4 :(得分:1)
代码始终是数据!程序的字节码指令存储在存储器中。程序员没有对此内存的直接读写访问权限,但它就在那里。
当我们谈论将“处理”代码作为数据时,我们指的是以对我们通常认为“数据”的方式使用和组织的方式存储对该内存的引用。
例如,可以想象在button
内部看起来像这样:
class Button {
private ActionListener[] listeners = new ActionListener[100];
private int count = 0;
public void addActionListener(ActionListener listener) {
listeners[count] = listener;
++count;
}
// called somehow when the button is clicked
void notifyListeners() {
ActionEvent theEvent = new ActionEvent(...);
for(int i = 0; i < count; ++i) {
listeners[i].actionPerformed(theEvent);
}
}
}
基本上Button
保留了数组中的函数列表:这是将代码视为数据。在大多数情况下,ActionListener
除了引用actionPerformed
的特定覆盖外,没有任何其他用途。
由于所有Java实例方法都是虚拟的,因此我们始终可以将代码视为数据。 AWT / Swing精心设计的事件监听框架证明了这一点。 Lambda表达式只是增加了概念强调和短语法。 (由于它们的实现,在大多数情况下也是性能提升。)
当我们仅使用对象来实现特定方法而不是存储值时,Lambdas允许我们更清楚地表达我们的意图。
从技术上讲,这都是通过间接完成的。 ActionListener
不包含代码:相反,虚拟机以某种方式(我们并不知情)知道它指向内存中包含指向代码的指针的特定结构。所以对代码的某种引用是实际传递的内容,因此“将代码视为数据”。