Что такое callback java
Перейти к содержимому

Что такое callback java

  • автор:

Что такое callback java

Одним из распространенных способов использования интерфейсов в Java является создание обратного вызова. Суть обратного вызова состоит в том, что мы создаем действия, которые вызываются при других действиях. То есть одни действия вызываются другими действиями. Стандартный пример — нажатие на кнопку. Когда мы нажимаем на кнопку, мы производим действие, но в ответ на это нажатие запускаются другие действия. Например, нажатие на значок принтера запускает печать документа на принтере и т.д.

Рассмотрим следующий пример:

public class EventsApp < public static void main(String[] args) < Button button = new Button(new ButtonClickHandler()); button.click(); button.click(); button.click(); >> class ButtonClickHandler implements EventHandler < public void execute()< System.out.println("Кнопка нажата!"); >> interface EventHandler < void execute(); >class Button < EventHandler handler; Button(EventHandler action)< this.handler=action; >public void click() < handler.execute(); >>

Итак, здесь у нас определен класс Button, который в конструкторе принимает объект интерфейса EventHandler и в методе click (имитация нажатия) вызывает метод execute этого объекта.

Далее определяется реализация EventHandler в виде класса ButtonClickHandler . И в основной программе объект этого класса передается в конструктор Button. Таким образом, через конструктор мы устанавливаем обработчик нажатия кнопки. И при каждом вызове метода button.click() будет вызываться этот обработчик.

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

Кнопка нажата! Кнопка нажата! Кнопка нажата!

Но казалось бы, зачем нам выносить все действия в интерфейс, его реализовать, почему бы не написать проще сразу в классе Button:

class Button < public void click()< System.out.println("Кнопка нажата!"); >>

Дело в том, что на момент определения класса нам не всегда бывают точно известны те действия, которые должны производиться. Особенно если класс Button и класс основной программы находятся в разных пакетах, библиотеках и могут проектироваться разными разработчиками. К тому же у нас может быть несколько кнопок — объектов Button и для каждого объекта надо определить свое действие. Например, изменим главный класс программы:

public class EventsApp < public static void main(String[] args) < Button tvButton = new Button(new EventHandler()< private boolean on = false; public void execute()< if(on) < System.out.println("Телевизор выключен.."); on=false; >else < System.out.println("Телевизор включен!"); on=true; >> >); Button printButton = new Button(new EventHandler() < public void execute()< System.out.println("Запущена печать на принтере. "); >>); tvButton.click(); printButton.click(); tvButton.click(); > >

Здесь у нас две кнопки — одна для включения-выключения телевизора, а другая для печати на принтере. Вместо того, чтобы создавать отдельные классы, реализующие интерфейс EventHandler, здесь обработчики задаются в виде анонимных объектов, которые реализуют интерфейс EventHandler. Причем обработчик кнопки телевизора хранит дополнительное состояние в виде логической переменной on .

В итоге консоль выведет нам следующий результат:

Телевизор включен! Запущена печать на принтере. Телевизор выключен..

И в завершении надо сказать, что интерфейсы в данном качестве особенно широко используются в различных графических API — AWT, Swing, JavaFX, где обработка событий объектов — элементов графического интерфейса особенно актуальна.

Что такое callback-интерфейсы и с чем их едят?

Изучая интерфейсы, наткнулся на такую штуку,как callbak-интерфейс. Если я правильно понял,то это интерфейс-маячок,который можно прикрутить к чему-нибудь,что будет дергать этот интерфейс в случае каких-либо изменений(например такой интерфейс можно весить на канал связи и в случае прихода сообщений выполнять какое-то действие) и он в свою очередь будет выполнять прописанные методы. Вопрос в том как его реализовывать.Примеры из туториалов,которые я нашел в сети мне не совсем понятны. Объясните пожалуйста, как реализуется эта штука, или поделитесь ссылками на хорошие материалы по данной теме.

Отслеживать
34.5k 15 15 золотых знаков 66 66 серебряных знаков 95 95 бронзовых знаков
задан 11 апр 2016 в 7:55
1,891 4 4 золотых знака 24 24 серебряных знака 39 39 бронзовых знаков

Для java эта тема широко освещена. Ещё есть Observer (наблюдатель). Ни одна книжка по java не обходится без Observer-а. Более древняя техника и наверное попроще. Без лишних объектов, прослоек. Прямо как вы хотите — интерфейс. А Listener предполагает передачу объекта-сообщения.

11 апр 2016 в 11:47

идея с Observer-ом мне понравилась,но Observer применяется наверное для масштабных проектов?к примеру у меня есть набор вебсокетных соединений. и есть одна точка,которая шлет сообщения в виде цифр. цифры собираются в коллекцию и расчитывается среднее значение,которое приходит клиентам на соккет. я хочу как-то фиксировать извмнение в коллекции,чтобы клиенты по ходу изменения коллекции получали измененное ср.значение коллекции,без обновления страницы. есть ли смысл реализовывать в таком случае этот паттерн?

12 апр 2016 в 7:59
Observer годится для всяких прожектов.
12 апр 2016 в 8:32

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

12 апр 2016 в 8:40

можно,но в моем случае вебсоккетное соединение сделано на vert.x 3. там вебсоккет выступает и как поток чтения и как поток записи(и кидать туда еще потоки, я думаю не целесообразно),тем не менее я так и не врубился,как сделать то,что описал выше средствами данного фреймворка,потому дошел до listener’ов

12 апр 2016 в 9:11

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

callback — обратный вызов — понятие и применение очень широкое.
callback-и вроде вашего маячка называют listener-ами(слушателями по-нашему). Они регистрируются функцией регистрации и потом вызываются не понятно кем и не известно когда (наступит событие или нет? когда? кто знает. )

Есть и другие виды callback-ов.

Например в Win32 APIесть функция EnumWindows для перечисления открытых окошек. Она принимает в качестве параметра функцию обратного вызова EnumWindowsProc .
EnumWindows знает что вам нужны эти окошки, но не знает зачем. Кроме того по каким-то важным причинам она не хочет выдавать Вам сразу готовый список.
Но с помощью callback она сдаст всех по-одному. Для каждого обнаруженного окошка вызывается Ваша функция EnumWindowsProc , чтобы в ней Вы сами разобрались с этим окошком. И здесь функция callback если будет вызвана, то только во время работы EnumWindows , а не когда-нибудь потом.

Что такое callback-функция в JavaScript?

Что такое callback-функция в JavaScript? главное изображение

Простыми словами: коллбэк — это функция, которая должна быть выполнена после того, как другая функция завершила выполнение (отсюда и название: callback — функция обратного вызова).

Чуть сложнее: В JavaScript функции — это объекты. Поэтому функции могут принимать другие функции в качестве аргументов, а также возвращать функции в качестве результата. Функции, которые это умеют, называются функциями высшего порядка. А любая функция, которая передается как аргумент, называется callback-функцией.

Зачем нужны коллбэки?

По одной простой причине: JavaScript — это событийно-ориентированный язык. Поэтому вместо того, чтобы ждать ответа для дальнейшего выполнения программы, JavaScript продолжит выполнение, одновременно ожидая других событий. Давайте разберем простой пример:

const first = () =>  console.log(1); >; const second = () =>  console.log(2); >; first(); second(); 

Как вы и ожидаете, функция first выполнится первой, а функция second уже после нее. Поэтому в консоли будет выведен следующий результат:

Пока что все понятно. Но что, если функция first содержит некий код, который не может выполниться немедленно? К примеру, работа с API, где мы отправляем запрос и должны ждать ответа. Чтобы смоделировать такую ситуацию, мы используем функцию setTimeout , которая вызывает функцию после заданного временного промежутка. Мы отсрочим выполнение функции на 500 миллисекунд, как будто бы это запрос к некому API. Теперь код будет выглядеть так:

const first = () =>  // Как будто бы запрос к API setTimeout(() =>  console.log(1); >, 500 ); >; const second = () =>  console.log(2); >; first(); second(); 

Неважно, понимаете ли вы сейчас, как работает setTimeout() . Основная идея — теперь мы отложили исполнение команды console.log(1) на 500 миллисекунд. И что теперь выведет наша программа?

Хотя мы по-прежнему вызываем функцию first первой, ее вывод появился вторым, после вывода функции second . Но JavaScript не нарушает порядок вызова функций, он просто не дожидается ответа от функции first , а сразу двигается дальше — к функции second .

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

Фронтенд-разработчик — с нуля до трудоустройства за 10 месяцев

  • Постоянная поддержка от наставника и учебного центра
  • Помощь с трудоустройством
  • Готовое портфолио к концу обучения
  • Практика с первого урока

Вы получите именно те инструменты и навыки, которые позволят вам найти работу

Создаем коллбэк

Во-первых, откройте консоль разработчика в Google Chrome (Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J), либо свой IDE, либо просто Repl.it , и введите в консоли следующую функцию:

const doHomework = (subject) =>  alert(`Starting my $subject> homework.`); >; 

Мы создали функцию doHomework . Наша функция принимает одну переменную — название предмета, которым мы будем заниматься. Вызовите функцию, набрав следующий текст в консоли:

doHomework('math'); // Выводит алерт: Starting my math homework. 

Теперь давайте добавим в определение функции еще один параметр, это и будет наш коллбэк. Затем вызовем ее, определив функцию-callback в качестве аргумента:

const doHomework = (subject, callback) =>  alert(`Starting my $subject> homework.`); callback(); >; doHomework('math', () =>  alert('Finished my homework'); >); 

Если вы введете этот код в консоли, вы получите два алерта один за другим, в первом будет сообщение о том, что выполнение домашнего задания началось (Starting my math homework.), а во втором — что вы закончили выполнять задание (Finished my homework).

Однако коллбэки не обязательно должны быть определены при вызове функции. Они могут быть определены и в другом месте кода, например, так:

const doHomework = (subject, callback) =>  alert(`Starting my $subject> homework.`); callback(); >; const alertFinished = () =>  alert('Finished my homework'); >; doHomework('math', alertFinished); 

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

Перепишем пример вызова функции с setTimeout для последовательного выполнения функций:

const first = (callback) =>  // Как будто бы запрос к API setTimeout(() =>  console.log(1); callback(); >, 500 ); >; const second = () =>  console.log(2); >; first(second); // 1 // 2 

Пример из реальной жизни

На прошлой неделе я опубликовал статью «Создаем бота для Твиттера в 38 строк кода» . Этот код работает благодаря API Твиттера. И когда мы делаем запрос к API, мы должны дождаться ответа до того, как начнем выполнять с этим ответом какие-то действия. Это прекрасный пример того, как в реальной жизни выглядит коллбэк. Вот как выглядит сам запрос:

T.get('search/tweets', params, (err, data, response) =>  if (!err)  // Происходит какая-то магия > else  console.log(err); > >); 

T.get просто значит, что мы выполняем get запрос к API Твиттера. В запросе три параметра: ‘search/tweets’ – это адрес (роут) запроса, params – наши параметры поиска и в конце передается анонимная функция-callback.

Коллбэк здесь нужен, потому что нам нужно дождаться ответа от сервера до того, как приступим к дальнейшему выполнению кода. Мы не знаем, успешным будет наш запрос или нет, поэтому после отправки параметров поиска на search/tweets через get-запрос, мы просто ждем. Как только Твиттер ответит, выполнится наша callback-функция. Твиттер отправит нам в качестве ответа или объект err (error – ошибка), или объект response. В коллбэке мы можем через if() проверить, был ли запрос успешным или нет, и затем действовать соответственно.

Профессия «Фронтенд-разработчик»

  • Изучите востребованные JavaScript и TypeScript
  • Научитесь создавать пользовательские интерфейсы сайтов и приложений
  • Освойте самый популярный фреймворк JavaScript — React
  • Познакомьтесь с языками веб-разработки HTML и CSS

Урок 13. Основы JAVA. Методы обратного вызова (callback)

Механизм обратного вызова(callbacks) широко распространен в программировании. При обратном вызове программист задает действия, которые должны выполняться всякий раз, когда происходит некоторое событие. И неважно, будете разрабатывать только java-программы или android-приложения – колбеки будут встречаться вам повсюду.

Для создания методов обратного вызова (callback) в java используются уже знакомые нам из прошлого урока интерфейсы.

Создадим новый класс SomeClass с интерфейсом Callback:

import javax.swing.*; public class SomeClass < // создаем колбек и его метод interface Callback< void callingBack(); >Callback callback; public void registerCallBack(Callback callback) < this.callback = callback; >void doSomething() < JOptionPane.showMessageDialog(null, "Выполняется работа"); // вызываем метод обратного вызова callback.callingBack(); >>

У интерфейса мы определили один метод callingBack(). Далее в классе мы создали объект интерфейса и инициализировали его в методе registerCallBack. В классе также был создан метод doSomething(), в котором может содержаться какой-то сложный код. Мы здесь создаем диалоговое окно, используя компонент JOptionPane библиотеки Swing. Кто не в курсе, Swing — библиотека для создания графического интерфейса программ на языке Java.

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

Теперь нам нужен класс, реализующий интерфейс-callback. Создаем класс MyClass и подключаем интерфейс-колбек через ключевое слово implements. Среда разработки заставит нас реализовать шаблон метода интерфейса.

public class MyClass implements SomeClass.Callback < @Override public void callingBack() < System.out.println("Вызов метода обратного вызова"); >>

Теперь мы можем использовать метод обратного вызова callingBack () для решения своих задач. Будем здесь выводить текст в консоль. Создадим класс Main, в котором будет реализован метод main – точка входа в программу.

public class Main < public static void main(String[] args) < SomeClass someClass = new SomeClass(); MyClass myClass = new MyClass(); //инициализируем колбек, передавая методу registerCallBack экземпляр MyClass, реализующий интерфейс колбек someClass.registerCallBack(myClass); someClass.doSomething(); >>

Здесь создаем экземпляры классов, инициализируем колбек, передавая методу registerCallBack экземпляр MyClass, реализующий интерфейс-callback. И вызываем метод doSomething();

При старте программы будет выполняться код метода doSomething(); из класса SomeClass. На экране появилось диалоговое окно.

2016-06-28_19-17-36

Когда мы нажмем кнопку, или закроем диалоговое окно, сработает метод обратного вызова callingBack(), который выведет сообщение в консоль.

Через интерфейс-callback также можно передавать какие-то данные. Давайте немного усложним пример.

package callback; import javax.swing.*; public class SomeClass < String replyTo; interface Callback< void callingBack(String s); >private Callback callback; public void registerCallBack(Callback callback) < this.callback = callback; >void doSomething() < int reply = JOptionPane.showConfirmDialog(null, "Вы программист?", "Опрос", JOptionPane.YES_NO_OPTION); if (reply == JOptionPane.NO_OPTION)< replyTo = "Нет"; >if (reply == JOptionPane.YES_OPTION) < replyTo = "Да"; >callback.callingBack(replyTo); > >

Объявим строковую переменную replyTo. Добавим аргумент метода callingBack – строковую переменную.

Изменим диалоговое окно – присвоим его новой целочисленной переменной reply, и изменим на showConfirmDialog, который имеет заголовок окна и больше одной кнопки ответа. В зависимости от нажатой кнопки переменной reply будет присвоено значение. Сравниваем ее значение с константой и присваиваем значение “Да” или “Нет” переменной replyTo.

Теперь внесем изменения в MyClass.

package callback; public class MyClass implements SomeClass.Callback < @Override public void callingBack(String s) < if (s != null) < System.out.println("Ваш ответ: " + s); >else < System.out.println("Вы не ответили на вопрос!"); >> >

Добавим аргумент в метод. И добавим условие проверки, что строка не пустая – это возможно, если вместо ответа просто закрыть диалоговое окно.

Класс Main без изменений.

package callback; public class Main < public static void main(String[] args) < SomeClass someClass = new SomeClass(); MyClass myClass = new MyClass(); someClass.registerCallBack(myClass); someClass.doSomething(); >>

Запускаем программу. Теперь текст сообщения в консоли меняется в зависимости от того, выберем мы да, нет или просто закроем окно.

2016-06-28_19-13-28

Я надеюсь, вы поняли принцип методов обратного вызова. Ниже есть ссылка на дополнительную информацию по колбекам, а также более сложные и познавательные примеры. Вопросы можно задавать в комментариях.

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

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