Есть ли способ передать функцию обратного вызова в методе Java?
Поведение, которое я пытаюсь имитировать, - это .Net Delegate, передаваемый в функцию.
Я видел людей, предлагающих создать отдельный объект, но это кажется излишним, однако я знаю, что иногда избыточное убийство - единственный способ сделать что-то.
java
callback
function-pointers
Омар Кохеджи
источник
источник
Ответы:
Если вы имеете в виду что-то вроде анонимного делегата .NET, я думаю, что анонимный класс Java также может быть использован.
источник
Начиная с Java 8, существуют ссылки на лямбда и методы:
Например, если вы хотите функциональный интерфейс,
A -> B
такой как:тогда вы можете назвать это так
Также вы можете передать метод класса. Скажем, у вас есть:
Тогда вы можете сделать:
Примечание :
Здесь я использовал функциональный интерфейс
Function<A,B>
, но в пакете есть много другихjava.util.function
. Самые известные из нихSupplier
:void -> A
Consumer
:A -> void
BiConsumer
:(A,B) -> void
Function
:A -> B
BiFunction
:(A,B) -> C
и многие другие, которые специализируются на некоторых типах ввода / вывода. Затем, если он не обеспечивает тот, который вам нужен, вы можете создать свой собственный функциональный интерфейс, например так:
Пример использования:
источник
java.util.function
том, что вы ищете, то вы можете пойти. Тогда вы можете играть с дженериками для ввода / вывода. (?)java.util.function
недостаточно.Для простоты вы можете использовать Runnable :
Использование:
источник
public interface SimpleCallback { void callback(Object... objects); }
Это довольно просто и может быть полезно, вам нужно также передать некоторые параметры.Немного придирки:
Передача обратного вызова включает создание отдельного объекта практически на любом языке ОО, так что вряд ли это можно считать излишним. Вероятно, вы имеете в виду, что в Java требуется создать отдельный класс, который является более многословным (и более ресурсоемким), чем в языках с явными первоклассными функциями или замыканиями. Тем не менее, анонимные классы, по крайней мере, уменьшают многословие и могут быть использованы встроенными.
источник
все же я вижу, что есть наиболее предпочтительный способ, который я искал ... он в основном получен из этих ответов, но мне пришлось манипулировать им, чтобы сделать его более излишним и эффективным. и я думаю, что все ищут то, что я придумаю
К точке::
сначала сделать интерфейс, который прост
теперь, чтобы запустить этот обратный вызов, когда вам захочется обработать результаты - более вероятно, что после асинхронного вызова вы захотите запустить некоторые вещи, которые зависят от этих результатов.
doSomething
это функция, которая занимает некоторое время, когда вы хотите добавить к ней обратный вызов, чтобы уведомить вас о результатах, добавить интерфейс обратного вызова в качестве параметра к этому методунадеюсь, моя точка зрения ясна, наслаждайтесь;)
источник
Это очень просто в Java 8 с лямбдами.
источник
Я нашел идею реализации с использованием библиотеки отражений интересной и придумал, что, я думаю, работает довольно хорошо. Единственным недостатком является потеря проверки времени компиляции, что вы передаете действительные параметры.
Вы используете это так
источник
Метод не является (пока) первоклассным объектом в Java; Вы не можете передать указатель на функцию в качестве обратного вызова. Вместо этого создайте объект (который обычно реализует интерфейс), который содержит необходимый метод, и передайте его.
Предложения по замыканиям в Java, которые обеспечили бы поведение, которое вы ищете, были сделаны, но ни одно из них не будет включено в предстоящий выпуск Java 7.
источник
Когда мне нужна такая функциональность в Java, я обычно использую шаблон Observer . Это подразумевает дополнительный объект, но я думаю, что это чистый путь, и это широко понятный шаблон, который помогает с читабельностью кода.
источник
Проверьте замыкания, как они были реализованы в библиотеке lambdaj. Они на самом деле ведут себя очень похоже на делегаты C #:
http://code.google.com/p/lambdaj/wiki/Closures
источник
Я попытался использовать java.lang.reflect для реализации 'обратного вызова', вот пример:
источник
timer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});
. выходной будетnull test: [null]
args[i].getClass()
? Я хочу сказать, что это не работает, если вы выбираете метод, основанный на типах аргументов. Это работает сString.format
, но может не работать с чем-то еще, что принимаетnull
.argTypes
массив вручную , поэтому теперь мы можем передаватьnull
аргумент / параметр без возникновения исключения NullPointerException. Пример вывода:NullParameterTest: String parameter=null, int parameter=888
Вы также можете сделать с
Callback
помощьюDelegate
шаблона:Callback.java
PagerActivity.java
CustomPagerAdapter.java
источник
Я недавно начал делать что-то вроде этого:
источник
он немного староват, но тем не менее ... Я нашел ответ Питера Уилкинсона хорошим, за исключением того факта, что он не работает для примитивных типов, таких как int / Integer. Проблема в
.getClass()
томparameters[i]
, что возвращает, напримерjava.lang.Integer
, который, с другой стороны, не будет правильно интерпретироватьсяgetMethod(methodName,parameters[])
(ошибка Java) ...Я совместил это с предложением Даниэля Спевака ( в его ответе на это ); Шаги к успеху включали: перехват
NoSuchMethodException
->getMethods()
-> поиск подходящего с помощьюmethod.getName()
->, а затем явный цикл по списку параметров и применение решения Дэниелса, например, определение совпадений типов и совпадений сигнатур.источник
Я думаю, что использование абстрактного класса более элегантно, например:
источник
object
чтобы один «уведомлял» другого,object
когда произошло что-то существенное, поэтому второйobject
может обработать событие. Вашеabstract class
никогда не является отдельнымobject
, это только отдельноеclass
. Вы используете только одинobject
и становитесь разнымиclasses
для выполнения разных функций, что является сущностью полиморфизма, а не шаблона обратного вызова.В принципе, если вы хотите создать объект интерфейса, это невозможно, потому что интерфейс не может иметь объекты.
Опция заключается в том, чтобы позволить некоторому классу реализовать интерфейс, а затем вызвать эту функцию, используя объект этого класса. Но этот подход действительно многословен.
В качестве альтернативы, напишите новый HelloWorld () (* oberserve, это интерфейс, а не класс), а затем выполните определение самих методов интерфейса. (* Это определение на самом деле является анонимным классом). Затем вы получаете ссылку на объект, через который вы можете вызвать сам метод.
источник
Создайте интерфейс и создайте то же свойство интерфейса в классе обратного вызова.
Теперь в классе, к которому вы хотите получить обратный вызов, реализуйте созданный выше интерфейс. а также Передайте «this» объект / ссылку вашего класса для повторного вызова.
источник