【问题标题】:Need help with callbacks and anonymous classes in Java在 Java 中的回调和匿名类方面需要帮助
【发布时间】:2009-05-28 01:08:26
【问题描述】:

我正在使用一些第三方库通过异步协议连接到服务器并获取响应。例如,通过用户名获取用户 ID 的方法如下所示:

public int getUserid(String username) {
        int userid = 0;

    connection.call("getUserid", new Responder() {
        public void onResult(final int result) {
            System.out.println("userid: " + result);
            //how to assign received value to userid and return it?
        }
    }, username);

    //wait for response
    while (userid == 0) {
            try{
                Thread.sleep(100);
            } catch (Exception e) {}
        }


        return userid;
}

问题是我无法将服务器响应返回的“结果”分配给方法中的“userid”变量(以便之后返回)。如何解决这个问题?我可能可以将它分配给某个类变量而不是方法变量,但我想将它保留在方法范围内,这样我就不必处理并发问题。

谢谢。

【问题讨论】:

    标签: java callback scope anonymous-class


    【解决方案1】:

    如果我正确理解您的问题,您是在问如何从匿名类中编写变量。

    匿名类只能访问最终变量,不能直接“写入”它们。

    一个“足够好”的直接解决方案是创建一种具有单个值字段和一个 getter 和 setter 的 ValueBox 类。然后,您可以在函数中实例化一个新变量作为最终变量,并让您的匿名类访问它。匿名类将使用它的 getter 和 setter 来写入/读取。

    变量是 final 的事实只是意味着您不能将引用指向其他任何地方,但您仍然可以从任一函数更改引用对象的内容。

    您将遇到的更大问题是等待回调被调用。这种等待睡眠可能足够好,但您可能需要考虑超时、线程等,具体取决于您要实现的目标。

    此外,这一切都假设您永远不会在连接上调用它两次。否则,您需要向我们提供有关您的同步模型的更多信息。

    这里有一些示例代码:

    public int getUserid(String username) {
            final ValueBox<Integer> userid = new ValueBox<Integer>();
    
            connection.call("getUserid", new Responder() {
                    public void onResult(final int result) {
                            System.out.println("userid: " + result);
                            userId.setValue(result);
                            //how to assign received value to userid and return it?
                    }
            }, username);
    
            //wait for response
            while (userid.isEmpty()) {
                    try{
                            Thread.sleep(100);
                    } catch (Exception e) {}
            }
    
          return userid.getValue();
    }
    

    【讨论】:

    • 谢谢。它需要被调用不止一次......你的意思是哪个同步模型,从这个 ValueBox 对象读/写?这将是相当复杂的......
    • 问题在于,在处理 userId 之前,您可能会多次调用 getUserId(例如,假设您在前 100 毫秒内有 5 次调用)。然后,您将面临被覆盖等风险。在这些情况下您想做什么?
    • 在当前请求完成之前可能不会处理进一步的请求。
    • 不需要同步,这是线程安全的。由于 userid 变量是一个方法局部变量,每次调用都会创建一个新实例,不需要什么特别的。
    【解决方案2】:

    最简单的更改是使用java.util.concurrent.SynchronousQueue 之类的内容。但可能你想自己提供一个事件驱动的接口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      • 1970-01-01
      相关资源
      最近更新 更多