Передача нулевой функции в функцию java в качестве аргумента - PullRequest
0 голосов
/ 28 января 2020

У меня возникают проблемы с пониманием того, как функции передаются в методы в качестве параметров.

Поиск в StackOverflow и StackExchange привел меня к решению с использованием java.util.Functions

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

(источник : https://codereview.stackexchange.com/questions/186972/passing-a-generic-function-as-parameter)

Хотя это решение мне кажется хорошим, я сталкиваюсь с проблемой, когда мне нужно передать функцию, которая предназначена для того, чтобы ничего не делать. Для лучшего понимания рассмотрим следующий пример:

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

Может ли кто-нибудь помочь мне получить ясное понимание по этой теме c? Большое вам спасибо.

Ответы [ 2 ]

4 голосов
/ 28 января 2020

Если вы хотите описать функцию, которая не возвращает значение, вы можете использовать тип Void. Это стандартный класс Java, но он предназначен для использования в этой ситуации.

Например,

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

Значение return null; важно, поскольку, с точки зрения компилятора, Void, как и любой другой класс (например, String, Integer, et c). Он не знает, что он представляет отсутствие значения, тогда как он знает, что функция, которая возвращает void, не имеет возвращаемого значения.

Это означает, что компилятор все еще ожидает некоторый оператор return в вашем коде, как если бы он возвращал Integer, и поэтому вы должны return null;

РЕДАКТИРОВАТЬ:

Однако вы можете обнаружить, что вы строго имеете дело с функциями с нет возврата, вы лучше использовать Consumer<T>. Например:

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

или, используя ссылку на метод:

Consumer<String> stringPrinter = System.out::println;
stringPrinter.accept("hello");
0 голосов
/ 28 января 2020

Вы можете использовать Reflection API для передачи метода void в качестве ссылки, например,

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

Вывод:

Hello world!
30
...