Я ищу способ передать метод по ссылке. Я понимаю, что Java не передает методы в качестве параметров, однако я хотел бы получить альтернативу.
Мне говорили, что интерфейсы являются альтернативой передаче методов в качестве параметров, но я не понимаю, как интерфейс может действовать как метод по ссылке. Если я правильно понимаю, интерфейс - это просто абстрактный набор методов, которые не определены. Я не хочу отправлять интерфейс, который нужно определять каждый раз, потому что несколько разных методов могут вызывать один и тот же метод с одинаковыми параметрами.
Чего я хотел бы достичь, так это чего-то подобного этому:
publicvoidsetAllComponents(Component[] myComponentArray, Method myMethod) { for (Component leaf : myComponentArray) { if (leaf instanceof Container) { //recursive call if Container Containernode= (Container) leaf; setAllComponents(node.getComponents(), myMethod); } //end if node myMethod(leaf); } //end looping through components }
Редактировать: начиная с Java 8, лямбда-выражения являются хорошим решением, как указывали другиеответы. Приведенный ниже ответ был написан для Java 7 и более ранних версий...
Редактировать: как указывает Пит Киркхэм, есть другой способ сделать это с помощью посетителя. Подход посетителя немного сложнее - все ваши узлы должны быть ориентированы на посетителя с помощью acceptVisitor() метода - но если вам нужно пройти более сложный объектный граф, тогда его стоит изучить.
Ответ 2
В Java 8 теперь вы можете передавать метод более легко, используя лямбда-выражения и ссылки на методы. Сначала немного предыстории: функциональный интерфейс - это интерфейс, который имеет один и только один абстрактный метод, хотя он может содержать любое количество методов по умолчанию (новых в Java 8) и статических методов. Лямбда-выражение может быстро реализовать абстрактный метод без всего ненужного синтаксиса, необходимого, если вы не используете лямбда-выражение.
Список формальных параметров, разделенных запятыми, заключен в круглые скобки. Метод CheckPerson.test содержит один параметр, p, который представляет экземпляр класса Person.
Примечание: Вы можете не указывать тип данных параметров в лямбда-выражении. Кроме того, вы можете не заключать в круглые скобки, если есть только один параметр. Например, также допустимо следующее лямбда-выражение:
Если вы укажете единственное выражение, среда выполнения Java вычислит выражение и затем вернет его значение. В качестве альтернативы, вы можете использовать оператор return:
Оператор return не является выражением; в лямбда-выражении вы должны заключать операторы в фигурные скобки ({}). Однако вам не обязательно заключать вызов метода void в фигурные скобки. Например, следующее является допустимым лямбда-выражением:
email -> System.out.println(email)
Обратите внимание, что лямбда-выражение очень похоже на объявление метода; вы можете рассматривать лямбда-выражения как анонимные методы —methods без имени.
Вот как вы можете "передать метод", используя лямбда-выражение:
Начиная с Java 8 существует Function<T, R> интерфейс (docs), в котором есть метод
R apply(T t);
Вы можете использовать его для передачи функций в качестве параметров другим функциям. T - тип ввода функции, R - тип возвращаемого значения.
В вашем примере вам нужно передать функцию, которая принимает Component тип в качестве входных данных и ничего не возвращает - Void. В данном случае Function<T, R> это не лучший выбор, поскольку отсутствует автоматическая вставка типа Void. Интерфейс, который вы ищете, вызывается Consumer<T> (docs) с помощью метода
Предполагается, что вы определили методы changeColor() и changeSize() в одном классе.
Если ваш метод принимает более одного параметра, вы можете использовать BiFunction<T, U, R> - T и U являются типами входных параметров, а R - типом возвращаемого значения. Также есть BiConsumer<T, U> (два аргумента, без возвращаемого типа). К сожалению, для 3 и более входных параметров вам придется создавать интерфейс самостоятельно. Например:
publicinterfaceFunction4<A, B, C, D, R> {
R apply(A a, B b, C c, D d); }
Ответ 4
Используйте java.lang.reflect.Method объект и вызывайте invoke