Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java8 pass a method as parameter using lambda

I would like to create a class that store a list of methods references and then executes all of them using Java 8 Lambda but I have some problem.

This is the class

public class MethodExecutor {
    //Here I want to store the method references
    List<Function> listOfMethodsToExecute = new LinkedList<>();

    //Add a new function to the list
    public void addFunction(Function f){
       if(f!=null){
            listOfMethodsToExecute.add(f);
       }
    }

    //Executes all the methods previously stored on the list
    public void executeAll(){
        listOfMethodsToExecute.stream().forEach((Function function) -> {
            function.apply(null);
        }
    }
}

This is the class that I created for test

public class Test{
    public static void main(String[] args){
        MethodExecutor me = new MethodExecutor();
        me.addFunction(this::aMethod);
        me.executeAll();    
    }

    public void aMethod(){
        System.out.println("Method executed!");
    }
}

But there is something wrong when I pass this::aMethod using me.addFunction.

What is wrong?

like image 734
user2572526 Avatar asked Aug 18 '15 14:08

user2572526


People also ask

How do you pass a method as lambda in Java?

Example 2: Pass multiline lambda body as function arguments languages. forEach((e) -> { // body of lambda expression String result = ""; for (int i = e. length()-1; i >= 0 ; i--) result += e. charAt(i); System.

Can you use a method as a parameter?

Parameters and Arguments Information can be passed to methods as parameter. Parameters act as variables inside the method. Parameters are specified after the method name, inside the parentheses. You can add as many parameters as you want, just separate them with a comma.

How do you pass a lambda function as a parameter?

Passing Lambda Expressions as Arguments You can pass lambda expressions as arguments to a function. If you have to pass a lambda expression as a parameter, the parameter type should be able to hold it. If you pass an integer as an argument to a function, you must have an int or Integer parameter.


2 Answers

You should provide a suitable functional interface which abstract method signature is compatible with your method reference signature. In your case it seems that Runnable instead of Function should be used:

public class MethodExecutor {
    List<Runnable> listOfMethodsToExecute = new ArrayList<>();

    //Add a new function to the list
    public void addFunction(Runnable f){
       if(f!=null){
            listOfMethodsToExecute.add(f);
       }
    }

    //Executes all the methods previously stored on the list
    public void executeAll(){
        listOfMethodsToExecute.forEach(Runnable::run);
    }
}

Also note that in static main method this is not defined. Probably you wanted something like this:

me.addFunction(new Test()::aMethod);
like image 72
Tagir Valeev Avatar answered Sep 28 '22 18:09

Tagir Valeev


You can't refer to this in a static context as there is no this

me.addFunction(this::aMethod);

You need to refer to an instance or define your Function to take a Test object.

public void addFunction(Function<Test, String> f){
   if(f!=null){
        listOfMethodsToExecute.add(f);
   }
}

and

me.addFunction(Test::aMethod);
like image 35
Peter Lawrey Avatar answered Sep 28 '22 18:09

Peter Lawrey