Java передать метод как параметр
Перейти к содержимому

Java передать метод как параметр

  • автор:

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

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

В этом руководстве описывается передача метода в качестве параметра в Java. Чтобы помочь вам разобраться в этой теме, мы включили примеры кодов.

В Java с нуля нет концепции метода передачи в качестве параметра. Однако мы можем добиться этого, используя ссылку на лямбда-функцию и метод в Java 8. Итак, в этой статье мы сосредоточимся на этих двух темах, чтобы передать метод в качестве параметра.

Please enable JavaScript

Лямбда-функция или лямбда-выражение — это концепция, которая была введена в Java 8. Это краткий способ написать функцию, следуя подходу функционального стиля. Поскольку Java и Java 8 считаются объектно-ориентированными языками, они поддерживают функциональный подход к написанию кода.

Передача метода в качестве параметра с помощью функции lambda в Java

Это простой пример лямбда-выражения, в котором мы используем его для перебора элементов ArrayList . Обратите внимание, что мы передаем лямбда-функцию методу forEach() интерфейса Iterable . Класс ArrayList реализует интерфейс Iterable .

Вот как мы можем передать метод (лямбда-функцию) в качестве параметра в Java:

Передача метода в качестве параметра пользовательскому методу в Java

Помимо встроенного метода forEach() , мы можем передать его в качестве параметра пользовательскому методу. В этом примере мы создали интерфейс Doable , имеющий метод doSomething() . В классе SimpleTesting есть метод show() , который вызывает метод doSomething() . Внутри метода main () мы создали лямбда-функцию и передали ее методу show() .

Обратите внимание, что это строка, в которой мы передаем метод (лямбда-функцию) в качестве параметра методу.

Передача метода в качестве параметра с помощью справочника по методам в Java

Это еще одно решение, которое можно использовать для передачи метода в качестве параметра методу. Он также был представлен с лямбда-функцией в версии Java 8. В этом примере мы использовали концепцию ссылки на метод, чтобы передать метод show() в качестве параметра конструктору Thread() , который выполняется во время выполнения. Смотрите вывод примера кода здесь:

Java передать метод как параметр

Лямбды как параметры методов

Одним из преимуществ лямбд в java является то, что их можно передавать в качестве параметров в методы. Рассмотрим пример:

Функциональный интерфейс Expression определяет метод isEqual() , который возвращает true, если в отношении числа n действует какое-нибудь равенство.

В основном классе программы определяется метод sum() , который вычисляет сумму всех элементов массива, соответствующих некоторому условию. А само условие передается через параметр Expression func . Причем на момент написания метода sum мы можем абсолютно не знать, какое именно условие будет использоваться. Само же условие определяется в виде лямбда-выражения:

То есть в данном случае все числа должны быть четными или остаток от их деления на 2 должен быть равен 0. Затем это лямбда-выражение передается в вызов метода sum.

При этом можно не определять переменную интерфейса, а сразу передать в метод лямбда-выражение:

Ссылки на метод как параметры методов

Начиная с JDK 8 в Java можно в качестве параметра в метод передавать ссылку на другой метод. В принципе данный способ аналогичен передаче в метод лямбда-выражения.

Ссылка на метод передается в виде имя_класса::имя_статического_метода (если метод статический) или объект_класса::имя_метода (если метод нестатический). Рассмотрим на примере:

Здесь также определен функциональный интерфейс Expression, который имеет один метод. Кроме того, определен класс ExpressionHelper, который содержит два статических метода. В принципе их можно было определить и в основном классе программы, но я вынес их в отдельный класс.

В основном классе программы LambdaApp определен метод sum() , который возвращает сумму элементов массива, соответствующих некоторому условию. Условие передается в виде объекта функционального интерфейса Expression.

В методе main два раза вызываем метод sum , передавая в него один и тот же массив чисел, но разные условия. Первый вызов метода sum :

На место второго параметра передается ExpressionHelper::isEven , то есть ссылка на статический метод isEven() класса ExpressionHelper. При этом методы, на которые идет ссылка, должны совпадать по параметрам и результату с методом функционального интерфейса.

При втором вызове метода sum отдельно создается объект Expression, который затем передается в метод:

Использование ссылок на методы в качестве параметров аналогично использованию лямбда-выражений.

Если нам надо вызвать нестатические методы, то в ссылке вместо имени класса применяется имя объекта этого класса:

Ссылки на конструкторы

Подобным образом мы можем использовать конструкторы: название_класса::new . Например:

При использовании конструкторов методы функциональных интерфейсов должны принимать тот же список параметров, что и конструкторы класса, и должны возвращать объект данного класса.

Лямбды как результат методов

Также метод в Java может возвращать лямбда-выражение. Рассмотрим следующий пример:

В данном случае определен функциональный интерфейс Operation, в котором метод execute принимает два значения типа int и возвращает значение типа int.

Метод action принимает в качестве параметра число и в зависимости от его значения возвращает то или иное лямбда-выражение. Оно может представлять либо сложение, либо вычитание, либо умножение, либо просто возвращает 0. Стоит учитывать, что формально возвращаемым типом метода action является интерфейс Operation, а возвращаемое лямбда-выражение должно соответствовать этому интерфейсу.

В методе main мы можем вызвать этот метод action. Например, сначала получить его результат — лямбда-выражение, которое присваивается переменной Operation. А затем через метод execute выполнить это лямбда-выражение:

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

Аватар пользователя Сергей Якимович

Передать метод в качестве параметра можно разными способами. Рассмотрим некоторые из них.

1) Воспользуемся функциональным интерфейсом Predicate :

2) Воспользуемся готовым функциональным интерфейсом UnaryOperator :

3) Создадим собственный интерфейс и передадим объект этого типа в нашу функцию :

Java Pass Method as Parameter

I am looking for a way to pass a method by reference. I understand that Java does not pass methods as parameters, however, I would like to get an alternative.

I’ve been told interfaces are the alternative to passing methods as parameters but I don’t understand how an interface can act as a method by reference. If I understand correctly an interface is simply an abstract set of methods that are not defined. I don’t want to send an interface that needs to be defined every time because several different methods could call the same method with the same parameters.

What I would like to accomplish is something similar to this:

invoked such as:

Arvind Kumar Avinash's user avatar

17 Answers 17

Edit: as of Java 8, lambda expressions are a nice solution as other answers have pointed out. The answer below was written for Java 7 and earlier.

Take a look at the command pattern.

Edit: as Pete Kirkham points out, there’s another way of doing this using a Visitor. The visitor approach is a little more involved — your nodes all need to be visitor-aware with an acceptVisitor() method — but if you need to traverse a more complex object graph then it’s worth examining.

In Java 8, you can now pass a method more easily using Lambda Expressions and Method References. First, some background: a functional interface is an interface that has one and only one abstract method, although it can contain any number of default methods (new in Java 8) and static methods. A lambda expression can quickly implement the abstract method, without all the unnecessary syntax needed if you don’t use a lambda expression.

Without lambda expressions:

With lambda expressions:

Syntax of Lambda Expressions

    A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p, which represents an instance of the Person class.

Here is how you can «pass a method» using a lambda expression:

Class C can be shortened even a bit further by the use of method references like so:

Since Java 8 there is a Function<T, R> interface (docs), which has method

You can use it to pass functions as parameters to other functions. T is the input type of the function, R is the return type.

In your example you need to pass a function that takes Component type as an input and returns nothing — Void . In this case Function<T, R> is not the best choice, since there is no autoboxing of Void type. The interface you are looking for is called Consumer<T> (docs) with method

It would look like this:

And you would call it using method references:

Assuming that you have defined changeColor() and changeSize() methods in the same class.

If your method happens to accept more than one parameter, you can use BiFunction<T, U, R> — T and U being types of input parameters and R being return type. There is also BiConsumer<T, U> (two arguments, no return type). Unfortunately for 3 and more input parameters, you have to create an interface by yourself. For example:

Use the java.lang.reflect.Method object and call invoke

First define an Interface with the method you want to pass as a parameter

Implement a class with the method

// Invoke like that

This allows you to pass cmd as parameter and invoke the method call defined in the interface

While this is not yet valid for Java 7 and below, I believe that we should look to the future and at least recognize the changes to come in new versions such as Java 8.

Namely, this new version brings lambdas and method references to Java (along with new APIs, which are another valid solution to this problem. While they still require an interface no new objects are created, and extra classfiles need not pollute output directories due to different handling by the JVM.

Both flavors(lambda and method reference) require an interface available with a single method whose signature is used:

Names of methods will not matter from here on. Where a lambda is accepted, a method reference is as well. For example, to use our signature here:

This is just a simple interface invocation, up until the lambda 1 gets passed:

This will output:

Method references are similar. Given:

the output would be real static method . Method references can be static, instance, non-static with arbitrary instances, and even constructors. For the constructor something akin to ClassName::new would be used.

1 This is not considered a lambda by some, as it has side effects. It does illustrate, however, the use of one in a more straightforward-to-visualize fashion.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *