首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java中的回调(代码解释)

Java中的回调(代码解释)
EN

Stack Overflow用户
提问于 2010-10-28 09:33:05
回答 5查看 11.8K关注 0票数 6

我在Java中遇到了一个关于回调的问题。她的是运行的代码和最初的答案这里

  1. 但我不明白这对回调有什么用?
  2. 你能向Java程序员解释回调的概念吗?

代码:

代码语言:javascript
运行
复制
public class Main {

    public interface Visitor {
        int DoJob(int a, int b);
    }


    public static void main(String[] args) {
        Visitor adder = new Visitor(){
            public int DoJob(int a, int b) {
                return a + b;
            }
        };

        Visitor multiplier = new Visitor(){
            public int DoJob(int a, int b) {
                return a*b;
            }
        };

        System.out.println(adder.DoJob(10, 20));
        System.out.println(multiplier.DoJob(10, 20));

    }
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-10-28 09:37:06

我曾经写过一篇关于http://madhurtanwani.blogspot.com/2010/09/callbacks-in-java.html的小博客文章。希望能帮上忙!

在我尝试解释上面的代码后,我必须说,这不是最直观或最好的使用回调。我在文章中使用的示例是Collections.sort(),它清楚地引出了回调部分。

对于上面发布的代码,Neverthelss可以这样想:

  1. main()函数实际上是一个数字(读取数据)流解析算法,它将解析一对数字(数据集),然后对它们进行操作。
  2. 现在,考虑到关注点的分离,main()函数不应该知道或理解可以对数据集执行哪些操作。事实上,它甚至不应该关心数据集的数据类型。
  3. 但是,由于这些数据集是特定于您的域的,因此主函数应该在理想情况下将数据的处理委托给特定于域的类。
  4. 要做到这一点,它必须与特定于域的调用方(main的调用方)强制执行一个契约,并且说-瞧,每当我接收到一对数据集时,我将在Visitor interface实现上调用该interface方法。调用方必须实现Visitor接口,并实现处理数据集的域特定逻辑。

处理从调用方委托回callee的部分称为使用interface (契约规范)在Java中实现的回调

票数 6
EN

Stack Overflow用户

发布于 2010-10-28 10:24:59

我不想在这里挑起火焰之战.但是回调的概念在C/C++、JavaScript、Python、可能是Ruby等语言中更容易理解。在这些语言中,回调只是一个函数指针。将函数作为此函数指针传递,其他代码将使用该指针调用您的函数。就这么简单。(请看维基百科的这个C示例)

但是Java没有函数指针,因此Java程序员需要使用匿名的内部类、接口和类似的东西,以便将函数封装在类中,并将该类的一个实例作为回调传递。

我想我已经回答了您的第二个问题(“您能向Java程序员解释回调的概念吗?”),但请参阅关于如何在Java中实现回调的其他答案。

票数 4
EN

Stack Overflow用户

发布于 2014-08-06 01:33:01

我以前是用Java开发的,直到我开始用C#及其委托进行编程,我才完全理解回调的概念。

这是因为正如@Denilson Sá完美地提到的那样,Java没有使用指向函数的指针。换句话说,在Java中,您可以调用一个方法并传递一些参数,例如原语值(int、long、char、boolean等)。和对象(字符串或任何类的任何实例,比如当您传递一个对象时,您基本上是在内存中的实际对象的内存中传递地址)。

Java中的回调概念可以通过使用接口并将它们(实现它们的对象)作为参数来实现。假设您有以下接口,该接口定义了任何类都必须作为ResultListener实现的方法。

代码语言:javascript
运行
复制
interface ResultListener {
   void onSuccessOperation(String description);
   void onFailedOperation(String description);
}

现在假设您有一个在showScreen方法中运行的主程序

代码语言:javascript
运行
复制
class MyMainScreen implements ResultListener {
   public void showScreen() {
    //do some things..
    SmartClass smartClass = new SmartClass();
    smartClass.divideAndNotify(5, 0, this);
    }

    public void onSuccessOperation(String description) {
       System.out.println("SUCCESS!!. " + description);
    }

    public void onFailedOperation(String description) {
       System.out.println("FAILED. " + description);
    }
}

这就是知道如何分裂的SmartClass。

代码语言:javascript
运行
复制
class SmartClass {
   public void divideAndNotify(int numerador, int denominador, ResultListener resultListener) {
        if (denominador == 0) {
            resultListener.onFailedOperation("Nobody can divide by zero!!");
        } else {
            int total = numerador / denominador;
            resultListener.onSuccessOperation("The result is " + total);
        }
    }
}    

这里有趣的部分是,MyMainScreen作为一个ResultListener运行,因此它需要实现接口ResultListener中定义的方法。MyMainScreen知道如何在控制台上打印消息,但它对计算一无所知,这就是为什么它实例化SmartClass来使用它的方法divideAndNotify,该方法接受两个数字,并引用将侦听结果的实例(在本例中,这个实例是MyMainScreen实例本身,这就是为什么它与单词 this 一起传递自己的原因)。

SmartClass方法divideAndNotify知道数学,并将操作结果通知正在侦听的人。它的方法知道resultListener将包含对一个对象的引用,当结果成功或不成功时,该对象知道该做什么。

这里的回调概念是,SmartClass将功能委托给如何处理结果,就像在作为参数接收到的实例中的“回调”一样。

总结:回调只是一个任务的委托。

PS:对于C#,这个概念要简单得多,因为C#有委托类型,这些变量存储函数所在的内存地址(存储的函数必须与委托中定义的签名匹配)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4041522

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档