在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);
  }
}

当前回答

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);
}

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

其他回答

使用lambda作为参数具有灵活性。它支持java中的函数式编程。基本语法是

Param -> method_body

下面是一种方法,您可以定义一个方法,将函数接口(使用lambda)作为参数。 a.如果你想在函数接口中定义一个方法, 例如,函数接口作为参数/参数提供给从main()调用的方法

@FunctionalInterface
interface FInterface{
    int callMeLambda(String temp);
}


class ConcreteClass{
        
    void funcUsesAnonymousOrLambda(FInterface fi){
        System.out.println("===Executing method arg instantiated with Lambda==="));
    }
        
    public static void main(){
        // calls a method having FInterface as an argument.
        funcUsesAnonymousOrLambda(new FInterface() {
        
            int callMeLambda(String temp){ //define callMeLambda(){} here..
                return 0;
            }
        }
    }
        
/***********Can be replaced by Lambda below*********/
        funcUsesAnonymousOrLambda( (x) -> {
            return 0; //(1)
        }
       
    }

FInterface fi = (x) ->{返回0;}; funcUsesAnonymousOrLambda (fi); 在上面我们可以看到,lambda表达式是如何被接口替换的。

以上解释了lambda表达式的一个特殊用法,还有更多。 裁判 Java 8 lambda内部的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);
}

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

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

Lambda表达式可以作为参数传递。要将lambda表达式作为参数传递,形参的类型(接收lambda表达式作为参数)必须为函数接口类型。

如果有功能接口-

interface IMyFunc {
   boolean test(int num);
}

还有一个filter方法,它只在int值大于5时才将int值添加到列表中。这里注意,filter方法有函数接口IMyFunc作为参数之一。在这种情况下,lambda表达式可以作为方法参数的参数传递。

public class LambdaDemo {
    public static List<Integer> filter(IMyFunc testNum, List<Integer> listItems) {
        List<Integer> result = new ArrayList<Integer>();
        for(Integer item: listItems) {
            if(testNum.test(item)) {
                result.add(item);
            }
        }
        return result;
    }
    public static void main(String[] args) {
        List<Integer> myList = new ArrayList<Integer>();
        myList.add(1);
        myList.add(4);
        myList.add(6);
        myList.add(7);
        // calling filter method with a lambda expression
        // as one of the param
        Collection<Integer> values = filter(n -> n > 5, myList);

        System.out.println("Filtered values " + values);
    }
}

有一个支持lambda的Java 8 JavaDocs的公共web可访问版本,链接到http://lambdafaq.org/lambda-resources。(这显然应该是对Joachim Sauer的回答的评论,但我无法进入我的SO帐户,我需要声望点来添加评论。)lambdafaq站点(由我维护)回答了这个问题和许多其他Java-lambda问题。

注意:这个答案是在Java 8 GA文档公开之前写的。不过,我把它留在了原处,因为Lambda FAQ对于学习Java 8中引入的特性的人来说可能仍然有用。