在Java 8中,方法可以创建为Lambda表达式,并且可以通过引用传递(在底层做一些工作)。网上有很多创建lambdas并将其与方法一起使用的示例,但没有示例说明如何创建以lambda作为参数的方法。它的语法是什么?

MyClass.method((a, b) -> a+b);


class MyClass{
  //How do I define this method?
  static int method(Lambda l){
    return l(5, 10);
  }
}

当前回答

对我来说,最有意义的解决方案是定义一个Callback接口:

interface Callback {
    void call();
}

然后在你想调用的函数中使用它作为参数:

void somewhereInYourCode() {
    method(() -> {
        // You've passed a lambda!
        // method() is done, do whatever you want here.
    });
}

void method(Callback callback) {
    // Do what you have to do
    // ...

    // Don't forget to notify the caller once you're done
    callback.call();
}

只是为了精确起见

lambda不是一个特殊的接口、类或任何你可以自己声明的东西。Lambda只是()->{}特殊语法的名称,它允许在作为参数传递单方法接口时具有更好的可读性。它的设计是为了取代这个:

method(new Callback() {
    @Override
    public void call() {
        // Classic interface implementation, lot of useless boilerplate code.
        // method() is done, do whatever you want here.
    }
});

所以在上面的例子中,Callback不是一个lambda,它只是一个常规接口;Lambda是可用于实现它的快捷语法的名称。

其他回答

Lambdas纯粹是一个调用站点构造:lambda的接收方不需要知道涉及到lambda,而是接受具有适当方法的Interface。

换句话说,您定义或使用一个函数接口(即具有单一方法的接口),该接口接受并返回您想要的内容。

自Java 8以来,Java .util.function中有一组常用的接口类型。

对于这个特定的用例,有java.util.function.IntBinaryOperator和一个int applyAsInt(int left, int right)方法,所以你可以这样写你的方法:

static int method(IntBinaryOperator op){
    return op.applyAsInt(5, 10);
}

但你也可以定义自己的接口,并像这样使用它:

public interface TwoArgIntOperator {
    public int op(int a, int b);
}

//elsewhere:
static int method(TwoArgIntOperator operator) {
    return operator.op(5, 10);
}

然后调用以lambda作为参数的方法:

public static void main(String[] args) {
    TwoArgIntOperator addTwoInts = (a, b) -> a + b;
    int result = method(addTwoInts);
    System.out.println("Result: " + result);
}

使用您自己的接口的好处是您可以使用更清楚地表明意图的名称。

下面是c#如何处理这个问题(但是用Java代码表示)。像这样的东西几乎可以满足你所有的需求:

import static org.util.function.Functions.*;

public class Test {

    public static void main(String[] args)
    {
        Test.invoke((a, b) -> a + b);       
    }

    public static void invoke(Func2<Integer, Integer, Integer> func)
    {
        System.out.println(func.apply(5, 6));
    }
}

package org.util.function;

public interface Functions {

    //Actions:
    public interface Action {
        public void apply();
    }

    public interface Action1<T1> {
        public void apply(T1 arg1);
    }

    public interface Action2<T1, T2> {
        public void apply(T1 arg1, T2 arg2);
    }

    public interface Action3<T1, T2, T3> {
        public void apply(T1 arg1, T2 arg2, T3 arg3);
    }

    public interface Action4<T1, T2, T3, T4> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
    }

    public interface Action5<T1, T2, T3, T4, T5> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
    }

    public interface Action6<T1, T2, T3, T4, T5, T6> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
    }

    public interface Action7<T1, T2, T3, T4, T5, T6, T7> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
    }

    public interface Action8<T1, T2, T3, T4, T5, T6, T7, T8> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
    }

    //Functions:
    public interface Func<TResult> {
        public TResult apply();
    }

    public interface Func1<T1, TResult> {
        public TResult apply(T1 arg1);
    }

    public interface Func2<T1, T2, TResult> {
        public TResult apply(T1 arg1, T2 arg2);
    }

    public interface Func3<T1, T2, T3, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3);
    }

    public interface Func4<T1, T2, T3, T4, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
    }

    public interface Func5<T1, T2, T3, T4, T5, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
    }

    public interface Func6<T1, T2, T3, T4, T5, T6, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
    }

    public interface Func7<T1, T2, T3, T4, T5, T6, T7, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
    }

    public interface Func8<T1, T2, T3, T4, T5, T6, T7, T8, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
    }
}

对于任何在谷歌上搜索这个的人来说,一个好方法是使用java.util.function. bicconsumer。 例:

Import java.util.function.Consumer
public Class Main {
    public static void runLambda(BiConsumer<Integer, Integer> lambda) {
        lambda.accept(102, 54)
    }

    public static void main(String[] args) {
        runLambda((int1, int2) -> System.out.println(int1 + " + " + int2 + " = " + (int1 + int2)));
    }

打印结果将是:166

基本上,要将lambda表达式作为参数传递,我们需要一个可以保存它的类型。就像我们在原始int或integer类中持有的整数值一样。Java没有单独的lambda表达式类型,而是使用接口作为类型来保存参数。但是这个接口应该是一个功能接口。

Lambda不是一个对象,而是一个功能接口。 使用@FuntionalInterface作为注释,可以定义尽可能多的功能接口

@FuntionalInterface
public interface SumLambdaExpression {
     public int do(int a, int b);
}

public class MyClass {
     public static void main(String [] args) {
          SumLambdaExpression s = (a,b)->a+b;
          lambdaArgFunction(s);
     }

     public static void lambdaArgFunction(SumLambdaExpression s) {
          System.out.println("Output : "+s.do(2,5));
     }
}

输出将如下所示

Output : 7

Lambda表达式的基本概念是定义自己的逻辑,但已经定义了参数。因此,在上面的代码中,您可以将do函数的定义从加法更改为任何其他定义,但参数限制为2。