我对 Lisp 中的 lambda 函数有很好的理解。 Java 似乎没有 Lisp 那样的灵 active 。我如何考虑 Java 中的 lambda?
鉴于下面的代码,我该怎么做?
public class Draw {
GraphicsContext gc;
static void draw(double x, double y, double w, double h, boolean drawRect) {
if (drawRect) {
gc.fillRect(x, y, w, h);
} else {
gc.strokeRect(x, y, w, h);
}
}
// How do I do that?
static void drawWithLambda(double x, double y, double w, double h /**, lambda */) {
lambda(x, y, w, h);
}
public static void main(String[] args) {
draw(0, 0, 50, 50, false); // OK
drawWithLambda(0, 0, 50, 50, GraphicsContext::fillRect); // Ok?
}
}
Java 中的 Lambda 与 functional interface 的概念结合使用.
典型的例子是Function
. Function
是一个功能接口(interface),其功能方法 apply
, 是一种采用单个参数并返回结果的方法。
您可以创建自己的函数式接口(interface),定义一个带有 4 个参数且没有返回类型的函数式方法,如下所示:
@FunctionalInterface
interface RectangleDrawer {
void draw(double x, double y, double w, double h);
}
(FunctionalInterface
注释不是绝对必要的,但它给出了明确的意图)。
然后您可以创建一个符合此功能接口(interface)约定的 lambda。典型 lambda syntax是 (方法参数) -> (lambda 主体)
。在此示例中,它将是:(x, y, w, h) -> gc.fillRect(x, y, w, h)
。这样编译是因为lambda声明了4个参数,没有返回类型,所以可以表示为之前定义的RectangleDrawer
的函数式方法。
你的例子会变成:
static GraphicsContext gc;
public static void main(String[] args) {
draw(0, 0, 50, 50, (x, y, w, h) -> gc.fillRect(x, y, w, h));
draw(0, 0, 50, 50, (x, y, w, h) -> gc.strokeRect(x, y, w, h));
}
static void draw(double x, double y, double w, double h, RectangleDrawer drawer) {
drawer.draw(x, y, w, h);
}
在这种特殊情况下,可以使用 method reference使用 ::
运算符创建 lambda,它允许编写更简单的代码:
static GraphicsContext gc;
public static void main(String[] args) {
draw(0, 0, 50, 50, gc::fillRect);
draw(0, 0, 50, 50, gc::strokeRect);
}
static void draw(double x, double y, double w, double h, RectangleDrawer drawer) {
drawer.draw(x, y, w, h);
}