Kwert-soft.ru

IT Софт для ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java callback пример

Блог только про Java

Учимся программировать на Java с нуля

Интерфейсы и обратный вызов

Механизм обратного вызова(callback) широко распространен в программировании. При обратном вызове программист задает действия, которые должны выполняться всякий раз, когда происходит некоторое событие. Например, можно задать действие, которое должно быть выполнено после щелчка на некоторой кнопке или при выборе определенного пункта меню. Мы рассмотрим простую ситуацию.

Пакет javax.swing содержит класс Timer, который можно использовать для отсчета интервалов времени. Например, если в программе предусмотрены часы, то с помощью класса Timer можно отсчитывать каждую секунду и обновлять циферблат часов.

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

Разумеется, таймер должен знать, какой метод он должен вызывать. Для этого таймеру нужно указать обьект класса, реализующего интерфейс ActionListener из пакета java.awt.event. Этот интерфейс выглядит следующим образом:

По истечении заданного интервала времени таймер вызывает метод actionPerformed().

Предположим, нам нужно каждый десять секунд выводить на экран сообщение о текущем времени, сопровождаемое звуковым сигналом. Для этого необходимо определить класс, реализующий интерфейс ActionListener, а затем поместить операторы, которые нужно выполнить, в тело метода actionPerformed().

Обратите внимание на параметр ActionEvent метода actionPerformed(). Он содержит информацию о событии, например, об объекте, его породившем. В данной программе детальная информация о событии не важна, поэтому можно просто проигнорировать этот параметр.

Затем следуют создать объект данного класса и передать его конструктору класса Timer:

Первый параметр конструктора Timer представляет собой интервал времени между точками отсчета, измеренный в миллисекундах. Сообщение должно выдаваться на экран каждые десять секунд. Второй параметр является объектом класса ActionListener.

Итак, запускаем таймер:

Каждые десять секунд на экране будет появляться следующее сообщение, сопровождаемое звуковым сигналом:

Звонок, время: Wed May 15 00:22:37 PDT 2013

После запуска таймера программа выводит на экран окно с сообщением и ждет, пока пользователь не щелкнет на кнопке ОК, чтобы завершить работу, при этом на экран каждые десять секунд выводится текущее время.

Будьте терпеливы. После того как диалоговое окно с вопросом Завершить программу? отобразится на экране, первое сообщение таймера появится только через десять секунд.

Интерфейсы

Ключевое слово interface используется для создания полностью абстрактных классов. Создатель интерфейса определяет имена методов, списки аргументов и типы возвращаемых значений, но не тела методов.

Наличие слова interface означает, что именно так должны выглядеть все классы, которые реализуют данный интерфейс. Таким образом, любой код, использующий конкретный интерфейс, знает только то, какие методы вызываются для этого интерфейса, но не более того.

Чтобы создать интерфейс, используйте ключевое слово interface вместо class. Как и в случае с классами, вы можете добавить перед словом interface спецификатор доступа public (но только если интерфейс определен в файле, имеющем то же имя) или оставить для него дружественный доступ, если он будет использоваться только в пределах своего пакета. Интерфейс может содержать поля, но они автоматически являются статическими (static) и неизменными (final). Все методы и переменные неявно объявляются как public.

Класс, который собирается использовать определённый интерфейс, использует ключевое слово implements. Оно указывает, что интерфейс лишь определяет форму, а вам нужно наполнить кодом. Методы, которые реализуют интерфейс, должны быть объявлены как public.

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

Читать еще:  Текст без ошибок

Интерфейсы могут вкладываться в классы и в другие интерфейсы.

Если класс содержит интерфейс, но не полностью реализует определённые им методы, он должен быть объявлен как abstract.

Интерфейсы — это не классы. С помощью ключевого слова new нельзя создать экземпляр интерфейса:

Но можно объявлять интерфейсные переменные:

При этом интерфейсная переменная должна ссылаться на объект класса, реализующего данный интерфейс.

Рассмотрим быстрый пример создания интерфейса. Выберите в меню File | New | Interface и придумайте имя для нового интерфейса. В полученной заготовке добавьте два имени метода (только имена, без кода).

Создайте или откройте какой-нибудь класс, к которому нужно применить интерфейс, и добавьте к нему implements SimpleInterface. Среда разработки подчеркнёт красной линией имя класса и предложит добавить методы, которые требуются интерфейсом. Соглашаемся и получаем результат:

Среда разработки сгенерировала два метода и использовала в качестве возвращаемых результатов значения по умолчанию. Это могут быть и нулевые значения и null. Осталось подправить шаблоны созданных методов под свои задачи. Например, так:

Первый метод возвращает имя класса, а второй — возраст кота (странно, что всем котам будет по пять лет, но это лишь пример).

Здесь важно понять роль интерфейса. Мы лишь придумываем имена, а класс уже реализует нужную задачу. Для примера можно создать в интерфейсе метод play() для класса Пианино и класса Гитара, так как играть можно на обеих инструментах. Но код в методах будет отличаться, так как принцип игры на инструментах совершенно разный.

Константы в интерфейсах

Интерфейсы можно использовать для импорта констант в несколько классов. Вы просто объявляете интерфейс, содержащий переменные с нужными значениями. При реализации интерфейса в классе имена переменных будут помещены в область констант. Поля для констант становятся открытыми и являются статическими и конечными (модификаторы public static final). При этом, если интерфейс не будет содержать никаких методов, то класс не будет ничего реализовывать. Хотя данный подход не рекомендуют использовать.

Расширение интерфейсов

Интерфейс может наследоваться от другого интерфейса через ключевое слово extends.

Методы обратного вызова

Интерфейсы часто используются для создания методов обратного вызова (callback). Рассмотрим такой пример. Создадим новый класс SubClass с интерфейсом MyCallback:

У интерфейса мы определили один метод callBackReturn(). Далее в классе мы создали объект интерфейса и инициализировали его в конструкторе класса. В классе также был создан метод doSomething(), в котором может содержаться какой-то сложный код. В конце метода вызывается метод интерфейса. В данном случае мы сами создали метод и знаем его код. Но во многих случаях, вы будете использовать готовый метод какого-то класса и вы не будете знать, что именно содержится в этом методе. Вам надо только знать, что такой метод существует, например, из документации и он выполняет конкретную задачу.

Переходим в код активности и подключаем интерфейс через ключевое слово implements:

Среда разработки поможет вставить шаблон метода интерфейса.

Теперь мы можем использовать метод обратного вызова callBackReturn() для решения своих задач. Допустим у нас есть текстовая метка и кнопка. При щелчке выполняется какой-то сложный код из класса SubClass. Когда он закончит работу, то сработает метод обратного вызова callBackReturn(), в котором пропишем нужные действия.

Слушатели

Очень часто для интерфейса используют слово Listener, например, у кнопки есть интерфейс OnClickListener.

Мы можем создавать подобные слушатели для собственных классов.

Также интерфейсы часто используются при работе с фрагментами.

Требуется определённая практика и опыт, чтобы быстро разбираться в коде с использованием интерфейсов, так как приходится отслеживать цепочку вызовов из разных классов. Но бояться их не нужно.

Callback functions in Java

Is there a way to pass a call back function in a Java method?

The behavior I’m trying to mimic is a .Net Delegate being passed to a function.

I’ve seen people suggesting creating a separate object but that seems overkill, however I am aware that sometimes overkill is the only way to do things.

Читать еще:  Int tostring java

17 Answers 17

If you mean somthing like .NET anonymous delegate, I think Java’s anonymous class can be used as well.

Since Java 8, there are lambda and method references:

For example, if you want a functional interface A -> B such as:

then you can call it like so

Also you can pass class method. Say you have:

Then you can do:

Note:

  • Supplier : void -> A
  • Consumer : A -> void
  • BiConsumer : (A,B) -> void
  • Function : A -> B
  • BiFunction : (A,B) -> C

and many others that specialize on some of the input/output type. Then, if it doesn’t provide the one you need, you can create your own functional interface like so:

For simplicity, you can use a Runnable:

A little nitpicking:

I’ve seem people suggesting creating a separate object but that seems overkill

Passing a callback includes creating a separate object in pretty much any OO language, so it can hardly be considered overkill. What you probably mean is that in Java, it requires you to create a separate class, which is more verbose (and more resource-intensive) than in languages with explicit first-class functions or closures. However, anonymous classes at least reduce the verbosity and can be used inline.

yet i see there is most preferred way which was what i was looking for.. it’s basically derived from these answers but i had to manipulate it to more more redundant and efficient.. and i think everybody looking for what i come up with

To the point::

first make an Interface that simple

now to make this callback run when ever you wish to do to handle the results — more likely after async call and you wanna run some stuff which depends on these reuslts

doSomething is the function that takes some time you wanna add a callback to it to notify you when the results came, add the call back interface as a parameter to this method

hope my point is clear, enjoy 😉

This is very easy in Java 8 with lambdas.

I found the idea of implementing using the reflect library interesting and came up with this which I think works quite well. The only down side is losing the compile time check that you are passing valid parameters.

You use it like this

A method is not (yet) a first-class object in Java; you can’t pass a function pointer as a callback. Instead, create an object (which usually implements an interface) that contains the method you need and pass that.

Proposals for closures in Java—which would provide the behavior you are looking for—have been made, but none will be included in the upcoming Java 7 release.

When I need this kind of functionality in Java, I usually use the Observer pattern. It does imply an extra object, but I think it’s a clean way to go, and is a widely understood pattern, which helps with code readability.

Check the closures how they have been implemented in the lambdaj library. They actually have a behavior very similar to C# delegates:

I tried using java.lang.reflect to implement ‘callback’, here’s a sample:

You also can do the Callback using the Delegate pattern:

I’ve recently started doing something like this:

it’s a bit old, but nevertheless. I found the answer of Peter Wilkinson nice except for the fact that it does not work for primitive types like int/Integer. The problem is the .getClass() for the parameters[i] , which returns for instance java.lang.Integer , which on the other hand will not be correctly interpreted by getMethod(methodName,parameters[]) (Java’s fault) .

Читать еще:  Класс calendar в java

I combined it with the suggestion of Daniel Spiewak (in his answer to this); steps to success included: catching NoSuchMethodException -> getMethods() -> looking for the matching one by method.getName() -> and then explicitly looping through the list of parameters and applying Daniels solution, such identifying the type matches and the signature matches.

I think using an abstract class is more elegant, like this:

Basically if you want to make the object of an interface it is not possible, because interface cannot have objects.

The option is to let some class implement the interface and then call that function using the object of that class. But this approach is really verbose.

Alternatively, write new HelloWorld() (*oberserve this is an interface not a class) and then follow it up with the defination of the interface methods itself. (*This defination is in reality the anonymous class). Then you get the object reference through which you can call the method itself.

Способы реализации функции (callback) функции обратного вызова в Java

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

Когда и где это может быть использовано?

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

Наш класс реализации диалогового окна готов, настал момент вывести его на экран, написав следующий код

В результате мы получим следующий результат на экране

Нажмем на кнопку и посмотрим на вывод в консоле NetBeans, где у нас ничего не выведется в первый раз, потому что диалоговое окно выполняется своим потоком, а программа своим и после нажатия на «ok» мы инициализируем значение поля result, закрываем диалоговое окно, но повторно — то этот код не выпонится, поэтому значение в result при первом запуске будет null, как мы его инициализировали в классе Dialog. При повторном выполнении данного кода у нас выведется тоже самое окно, но значение уже будет не текущее, а предыдущего нажатия, что не есть нормально, так как создается 2 потока: 1- поток программы, 2 — поток диалогового окна.

Решение проблемы с помощью callback

Код ниже именуется как callback .

Callback не возвращает type, как вы можете видеть выше в примере, он void .

Callback — и имеют методы, которые вы получаете как аргументы в другом методе. Другой метод должен вызвать callback метод, когда он пожелает. Это значит, что callback — и имеют асинхронность.

В вашем примере, он вызывает callback, когда вы жмете на кнопку.

И в заключении, вы не сможете возвратить его, используя return.

Что делать ?

Вы можете вызвать метод из вашего callback и отправить ваше возвращаемое значение ему как аргумент.

Где setReturnValue -метод принадлежащий вашему классу YourClass или его экземпляр, который будет содержать ваше возвращаемое значение.

Другой и лучшим путем подхода будет создание класса, который будет наследовать Stage. Также в вашем showPrompt методе вы должны блокировать выполнение основного потока, используя showAndWait() или похожим образом.

В заключении, вы не можете создавать весь Prompt из только одного метода.

Ссылка на основную публикацию
Adblock
detector