Что такое метод обратного вызова в Java? (Термин, кажется, используется свободно)
Я не понимаю, что такое метод обратного вызова, и я слышал, что люди используют этот термин очень свободно. Что такое метод обратного вызова в мире Java? Если бы кто-то мог предоставить пример кода метода обратного вызова Java с объяснением, это было бы большим подспорьем в моем изучении Java.
Заранее спасибо.
Ответы
Ответ 1
Обратный вызов - это фрагмент кода, который вы передаете в качестве аргумента для другого кода, чтобы он выполнял его. Поскольку Java еще не поддерживает указатели на функции, они реализованы как объекты Command. Что-то вроде
public class Test {
public static void main(String[] args) throws Exception {
new Test().doWork(new Callback() { // implementing class
@Override
public void call() {
System.out.println("callback called");
}
});
}
public void doWork(Callback callback) {
System.out.println("doing work");
callback.call();
}
public interface Callback {
void call();
}
}
Обратный вызов обычно содержит ссылку на какое-то состояние, чтобы на самом деле было полезно.
Благодаря тому, что реализация обратного вызова имеет все зависимости от вашего кода, вы получаете косвенное отношение между вашим кодом и кодом, выполняющим обратный вызов.
Ответ 2
Метод обратного вызова в java - это метод, который вызывается, когда происходит событие (называет его E
). Обычно вы можете реализовать это, передав реализацию определенного интерфейса системе, которая отвечает за запуск события E
(см. Пример 1).
Также в более крупных и сложных системах вы можете просто аннотировать метод, и система будет идентифицировать все аннотированные методы и вызовет их при возникновении события (см. пример 2). Конечно, система определяет, какие параметры должен получить метод и другие ограничения.
Пример 1:
public interface Callback {
//parameters can be of any types, depending on the event defined
void callbackMethod(String aParameter);
}
public class CallbackImpl implements Callback {
void callbackMethod(String aParameter) {
//here you do your logic with the received paratemers
//System.out.println("Parameter received: " + aParameter);
}
}
//.... and then somewhere you have to tell the system to add the callback method
//e.g. systemInstance.addCallback(new CallbackImpl());
Пример 2:
//by annotating a method with this annotation, the system will know which method it should call.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CallbackAnnotation {}
public class AClass {
@CallbackAnnotation
void callbackMethod(String aParameter) {
//here you do your logic with the received paratemers
//System.out.println("Parameter received: " + aParameter);
}
}
//.... and then somewhere you have to tell the system to add the callback class
//and the system will create an instance of the callback class
//e.g. systemInstance.addCallbackClass(AClass.class);
Ответ 3
Простыми словами... Говоря простым языком, функция обратного вызова похожа на Работника, который "перезванивает" своему Менеджеру после завершения Задачи.
Чем они отличаются от вызова одной функции из другой, принимая некоторый контекст из вызывающей функции? Это правда, что вы вызываете функцию из другой функции, но суть в том, что обратный вызов обрабатывается как объект, поэтому вы можете изменить, какую функцию вызывать, основываясь на состоянии системы (например, шаблон проектирования стратегии).
Как объяснить их силу начинающему программисту? Мощь обратных вызовов можно легко увидеть на веб-сайтах в стиле AJAX, которым необходимо получать данные с сервера. Загрузка новых данных может занять некоторое время. Без обратных вызовов весь пользовательский интерфейс "зависнет" при загрузке новых данных, или вам нужно будет обновить всю страницу, а не только ее часть. С помощью функции обратного вызова вы можете вставить "загружаемое" изображение и заменить его новыми данными после загрузки.
Некоторый код без обратного вызова:
function grabAndFreeze() {
showNowLoading(true);
var jsondata = getData('http://yourserver.com/data/messages.json');
/* User Interface 'freezes' while getting data */
processData(jsondata);
showNowLoading(false);
do_other_stuff(); // not called until data fully downloaded
}
function processData(jsondata) { // do something with the data
var count = jsondata.results ? jsondata.results.length : 0;
$('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
$('#results_messages').html(jsondata.results || '(no new messages)');
}
С обратным вызовом : Вот пример с обратным вызовом, использующим jQuery getJSON:
function processDataCB(jsondata) { // callback: update UI with results
showNowLoading(false);
var count = jsondata.results ? jsondata.results.length : 0;
$('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
$('#results_messages').html(jsondata.results || '(no new messages)');
}
' 'function grabAndGo() { // and don't freeze
showNowLoading(true);
$('#results_messages').html(now_loading_image);
$.getJSON("http://yourserver.com/data/messages.json", processDataCB);
/* Call processDataCB when data is downloaded, no frozen User Interface!
do_other_stuff(); // called immediately
Ответ 4
Проще говоря, механизм обратного вызова относится к вызову функции с другой функцией в качестве аргумента. В таких языках, как C, C++ это делается путем передачи указателей на функции в качестве аргументов, но java не имеет понятия указателей. Обходной путь - это интерфейсы. Мы передаем ссылку на интерфейсы вместо указателей. Ваше понимание будет кристально чистым после понимания кода ниже. Чтобы также показать реальные приложения, представьте себе покупку мыши и коврика для мыши. Цена коврика для мыши фиксирована, но цена мыши зависит от бренда.
interface mouse
{
double mousePrice();
}
class BrandA implements mouse
{
public double mousePrice() //note that public access modifier is needed as all methods of interface are public are by default and when you override them
//you cannot use any access modifier more restrictive
{
return 100;
}
}
class BrandB implements mouse
{
public double mousePrice()
{
return 200;
}
}
class Simple
{
static void total(mouse t)
{
double mousepad = 20;
double mousep = t.mousePrice();
System.out.println(mousepad + mousep);
}
public static void main(String args[])
{
mouse ob = new BrandA(); //upcasting.
total(ob);
}
}