一个函数对象就是这样。某物既是物体又是功能。
另外:调用函数对象是一个“函子”,严重地滥用了这个术语:一种不同的“函子”是数学中的核心概念,而在计算机科学中是直接的(见“Haskell Functors”)。该术语在ML中也略有不同,所以除非你在Java中实现这些概念之一(可以!),请停止使用这个术语。它使简单的事情变得复杂。
回到答案:
Java没有“第一类函数”,也就是说,不能将函数作为参数传递给函数。在语法上,在字节码表示中,在多个层次上是真实的,并且类型系统缺少“函数构造函数”
换句话说,你不能写这样的东西:
public static void tentimes(Function f){
for(int i = 0; i < 10; i++)
f();
}
...
public static void main{
...
tentimes(System.out.println("hello"));
...
}
这真的很烦人,因为我们希望能够像图形用户界面库这样做,可以将“回调”功能与点击按钮相关联。
那么我们该怎么办?
那么一般的解决方案(由其他海报讨论)就是用一个可以调用的方法定义一个接口。例如,Java对于这些类型的东西一直使用一个称为Runnable的接口,它看起来像:
public interface Runnable{
public void run();
}
现在我们可以从上面重写我的例子:
public static void tentimes(Runnable r){
for(int i = 0; i < 10; i++)
r.run();
}
...
public class PrintHello implements Runnable{
public void run{
System.out.println("hello")
}
}
---
public static void main{
...
tentimes(new PrintHello());
...
}
显然,这个例子是被设计的。我们可以使用匿名内部类使这个代码更好一点,但是这得到了一般的想法。
这里是分解的:Runnable仅适用于不接受任何参数的函数,并且不返回任何有用的东西,因此最终为每个作业定义一个新界面。例如,Mohammad Faisal的答案中的比较器接口。提供更一般的方法,而采用语法的方法是Java 8(下一个版本的Java)的主要目标,并被大量推送到Java 7中。在函数抽象机制之后被称为“lambda”在Lambda微积分。 Lambda微积分既是(也许)最古老的编程语言,也是计算机科学的理论基础。当Alonzo教堂(计算机科学的主要创始人之一)发明了它时,他使用希腊字母lambda作为功能,因此名称。
其他语言,包括功能语言(Lisp,ML,Haskell,Erlang等),主要的动态语言(Python,Ruby,JavaScript等)和其他应用程序语言(C#,Scala,Go,D等)支持某种形式的“Lambda文字”。即使C现在有了(从C11起),尽管在这种情况下,它们稍微复杂一些,因为C缺少自动内存管理,不会为你保存堆栈框架。