Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Передача метода в качестве параметра в java

#java


Читал новые фичи в java 8, но так и не понял, можно ли в java передать метод в качестве
параметра другому методу?
    


Ответы

Ответ 1



Насколько я понимаю, речь всё-таки не о лямбда-выражениях, а о ссылках на методы (method references). Они ходят рядом с лямбда-выражениями, но всё же это отдельная штука. Предположим, у вас есть метод, которому зачем-то посреди работы нужно преобразование строки в строку. Для этого можно воспользоваться готовым функциональным интерфейсом UnaryOperator: public void myMethod(UnaryOperator stringTransformer) { // где-то в середине метода, возможно даже в цикле String transformedString = stringTransformer.apply(str); ... } Теперь в этот метод вы можете передать ссылки на подходящие методы. Тут подходят некоторые методы класса String, которые не принимают аргументов и возвращают новую строку. Например, можно вызвать так: myMethod(String::trim); Или так: myMethod(String::toUpperCase); Тогда, когда вы вызываете stringTransformer.apply(str), это волшебным образом превратится в str.trim() или str.toUpperCase(). Ещё тут вариант — передать ссылку на статический метод с одним параметром. Например, у вас в проекте есть такое: public class StringUtils { public static String removeDots(String str) { return str.replace(".", ""); } } Тогда вы можете и ссылкой на такой метод воспользоваться: myMethod(StringUtils::removeDots); И stringTransformer.apply(str) волшебным образом превратится в StringUtils.removeDots(str). Ещё можно сделать instance-bound ссылку, привязанную к конкретному объекту. Например: myMethod(Pattern.compile("foo").matcher("[foo]")::replaceFirst); Тут уже stringTransformer.apply(str) волшебным образом возьмёт str в квадратные скобки (а точнее — заменит в [foo] подстроку foo на str). Есть ещё ссылки на методы, создающие объект (типа ArrayList::new) или массив (типа int[]::new). В этом случае функциональный интерфейс должен соответствовать параметрам конструктора (в случае массива подразумевается один целый параметр — его длина). Ссылки на методы — мощная и красивая штука, но нередко всё-таки нужно полноценное лямбда-выражение. Например, последний пример яснее написать так: myMethod(str -> "["+str+"]");

Ответ 2



Очень просто. Лямбды в Java — не что иное, как интерфейсы с одним методом. Поэтому вы можете на выбор либо определить такой интерфейс сами, либо воспользоваться готовыми интерфейсами отсюда (возможно, вам придётся боксировать примитивные типы при этом). Пример: // определяем свой интерфейс interface NameAndIndexPredicate { public boolean execute(String name, int index); } boolean apply(NameAndIndexPredicate p, String name, int index) { return p.execute(name, index); } apply((n, i) -> true, "VladD", 1); import java.util.function.*; // пользуемся готовым интерфейсом boolean apply(BiPredicate p, String name, int index) { return p.test(name, index); } apply((n, i) -> true, "VladD", 1); Как правильно заметил @Tagir Valeev, метод можно передать в функцию точно так же, как и лямбду. Смотрите его ответ по поводу синтаксиса передачи методов.

Комментариев нет:

Отправить комментарий