0

I'm encountering problems understanding how function are passed to methods as parameters.

Searching on StackOverflow and StackExchange has brought me to a solution using java.util.Functions

public void someFunction(Functions <int[], int[]> myFunction);

(source: https://codereview.stackexchange.com/questions/186972/passing-a-generic-function-as-parameter)

Although this solution seems good to me, I'm facing problem when I need to pass a function which is intended to do nothing. For better understanding, consider the following example:

public class Example {
    //do stuffs
    myFunction(null);
}

public class Manager {
    public void myFunction(Function<int[], void> funcToPass) { // Can't specify void as return value!
        //do stuff
        if(funcToPass != null) { // can't replicate such behaviour
            funcToPass(someParams)
        }
    }
}

Can someone help me acquiring clear understanding on this topic? Thank you so much.

8
  • 1
    a Function without return is just a Consumer Commented Jan 27, 2020 at 22:31
  • I do not consider this a valid answer since I need a more general case. Consumer would limit me to consider only functions with Void return value. Commented Jan 27, 2020 at 22:36
  • 1
    sure not a valid answer, it is just a comment. but if you define your method that way, there is no way to change the function to return anything but what is declared (Void) - anyway that does not matter for question, so I posted it as comment and not answer. And why "can't replicate such behaviour"? should work with Java (assuming correct declaration of function) Commented Jan 27, 2020 at 22:38
  • 1
    but it does work (again, assuming correct declaration) Commented Jan 27, 2020 at 22:48
  • 1
    just for knowledge: funcToPass will be a reference to an instance as any parameter that is not of primitive type (mini-example). In this case implements Function, is of type Function Commented Jan 27, 2020 at 23:08

2 Answers 2

4

If you want to describe a function that does not return a value, you can use the Void type. This is a standard Java class, but is intended for use in this situation.

E.g.

Function<String, Void> stringPrinter = s -> {
    System.out.println(s);
    return null;  // must return some value, null is acceptable since there is no Void instance
};

The return null; is important since, from the compiler's point of view, Void is just like any other class (e.g. String, Integer, etc). It doesn't know that it represents the absence of a value, whereas it does know that a function that returns void does not have a return value.

This means the compiler still expects some return statement in your code, just as if it were returning an Integer, and so you must return null;

EDIT:

You may find, however, if you are strictly dealing with functions with no returns, you are better suited to use a Consumer<T>. For example:

Consumer<String> stringPrinter = s -> System.out.println(s);
stringPrinter.accept("hello");

or, using a method reference:

Consumer<String> stringPrinter = System.out::println;
stringPrinter.accept("hello");
Sign up to request clarification or add additional context in comments.

5 Comments

actually return null is the only option, not just acceptable, since there is no possible instance of Void
This means I can use a lambda function which returns null as a result?
Another question: it is not possible then to pass null as function parameter instead of this place-filler function?
null is a valid value for all classes in Java, so you can pass null to any parameter that expects a class (i.e. any type except int, long, etc). However, calling function.apply(someValue) will throw a NullPointerException if function is null.
well so if I just check null value I solved my problem... trying this right now
0

You can use Reflection API to pass a void method as a reference e.g.

import java.lang.reflect.Method;

public class Main {

    public static void main(String[] args) throws Exception {
        Class[] classParams = new Class[1];
        classParams[0] = String.class;
        Method method = Main.class.getMethod("hello", classParams);
        Main obj = new Main();
        System.out.println(new Main().getSum(obj, method, "world!", 10, 20));
    }

    public void hello(String msg) {
        System.out.println("Hello " + msg);
    }

    int getSum(Object object, Method method, String msg, int x, int y) throws Exception {
        Object[] objectParams = new Object[1];
        objectParams[0] = msg;
        method.invoke(object, objectParams);
        return x + y;
    }
}

Output:

Hello world!
30

5 Comments

While this does work, the type safety and performance costs do not justify using reflection in this case, especially when there are good alternative solutions
So, if I'm not wrong, this works by passing parameters of hello method as classParams variable of type Class?
Parameter to hello method is "world!". Basically, you are passing method as the reference of hello method to getSum method from where you are invoking hello method using the reference.
Subtle, but indeed a possible solution.
Thanks, @KingPowa for the feedback.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.