【问题标题】:Method returns wrong value because return is too early方法返回错误的值,因为返回太早
【发布时间】:2019-10-08 08:54:07
【问题描述】:

很抱歉这个奇怪的主题标题,但我不知道如何比这更好地描述我的问题。

我目前正在开发一个使用 Microsoft Graph API 的 Java 项目(这是我第一次使用 Microsoft Graph API)。

我认为我的问题是 Java 的一般问题。我有一个类提供 Graph API 客户端和第二个类,其中包含我想使用 Graph API 执行的所有操作。具有操作方法的类应将结果返回给客户端类。

一些代码。 我的客户端类(我调用操作的相关部分):

client = GraphServiceClientManager.getInstance().getGraphServiceClient();
Operations task = new Operations(client);
System.out.println(task.getUsernamebyUPN("USER UPN"));

我的班级与操作:

public String username = "0";

    public String getUsernamebyUPN(String UPN) {
       client.users(UPN).buildRequest().get(new ICallback<User>() {
            @Override
            public void success(User user) {
                username = user.displayName;

            }

            @Override
            public void failure(ClientException ex) {
                ex.printStackTrace();
            }
        });
        return username;
    }

所以问题是当我运行代码时,它会返回值为 0 的用户名,而不是我想要的用户名。返回后用户名变量会发生变化。

如果我在“username = user.displayName;”下添加一个 System.out.prntln(username)成功方法中的行我的输出将是:

0
The username I want

我该如何解决这个问题?您需要更多代码吗?

非常感谢您的帮助。 :)

【问题讨论】:

  • 您不能从使用回调机制的方法返回值。相反,在回调本身中进行所需的更改。或者使用一些通知系统来告诉您何时发生回调。
  • 或许可以试试:OperatorClassName.this.username=user.displayName;
  • @HovercraftFullOfEels 因为这是一个匿名类,根据:docs.oracle.com/javase/tutorial/java/javaOO/…“匿名类可以访问其封闭类的成员。”
  • @Maryam:只有当匿名类有一个隐藏变量的字段时才重要。这个没有,所以你的建议没有任何好处。 OP 的代码已经按照您的建议告诉他要执行的操作。这里的问题是并发性而不是变量引用。
  • 感谢您的快速回复。 @HovercraftFullOfEels 你的帖子帮助了我,我想我修好了,明天再测试。

标签: java methods return return-value


【解决方案1】:

该值将异步返回给回调函数,但您可以强制您的程序在需要该值时等待返回。一种方法是返回一个值持有者类,当您尝试获取该值时该类会阻塞,直到它被设置,然后回调设置该值。

例如,以下类使用 Phaser 来控制这种等待行为:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Phaser;

public class FutureValue<T> {

    private T value = null;
    private Exception ex = null;
    private Phaser phaser = new Phaser(1);

    /**
     * Get blocks until a value or an exception is set, after that it always
     * returns immediately
     *
     * @return the value
     * @throws ExecutionException
     */
    public T get() throws ExecutionException {
        phaser.register();
        phaser.arriveAndAwaitAdvance();
        if (ex != null) {
            throw new ExecutionException(ex);
        }
        return value;
    }

    /**
     * Sets the value and unblocks awaiting threads
     *
     * @param val
     */
    public void set(T val) {
        this.value = val;
        phaser.forceTermination();
    }

    /**
     * Sets an exception and unblocks awaiting threads
     */
    public void setException(InterruptedException ex) {
        this.ex = ex;
        phaser.forceTermination();
    }
}

您可以更改方法以返回 FutureValue:

    public FutureValue<String> getUsernamebyUPN(String UPN) {

       final FutureValue<String> future = new FutureValue<String>();
       client.users(UPN).buildRequest().get(new ICallback<User>() {
            @Override
            public void success(User user) {
                future.set(user.displayName);
            }

            @Override
            public void failure(ClientException ex) {
                future.setException(ex);
            }
        });
        return future;
    }

另一种选择是将您的逻辑更改为不获取值,而是观察事件,回调发送事件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2018-10-11
    • 2019-10-12
    • 2021-01-25
    • 2020-08-10
    • 2016-02-01
    • 1970-01-01
    相关资源
    最近更新 更多