方法返回错误的值,因为返回时间太早

时间:2019-05-21 22:34:48

标签: java methods return return-value

对于那个奇怪的线程标题很抱歉,但是我不知道该如何更好地描述我的问题。

我目前正在研究一个使用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的用户名,而不是我想要的用户名。返回后将更改用户名变量。

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

0
The username I want

如何解决此问题?您需要更多代码吗?

非常感谢您的帮助。 :)

1 个答案:

答案 0 :(得分:0)

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

例如,以下类使用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;
    }

另一种选择是更改逻辑,使其不获取值,而是观察事件,并通过回调发送事件。