重复调用将 Retrofit 网络调用排入队列的静态方法是否会相应地维护传递参数的值?

Does repetitively calling a static method that enqueues a Retrofit network call maintain the value of the passed arguments correspondingly?

 public static void sendFeedback(final Feedback feedback, final Context context) {
    Call<MyServerResponse> sendFeedbackCall = service.sendFeedback(feedback);

    sendFeedbackCall.enqueue(new Callback<MyServerResponse>() {
        @Override
        public void onResponse(@NonNull Call<MyServerResponse> call, @NonNull Response<MyServerResponse> response) {
            if (response.isSuccessful()) {
                feedback.setSent(true); // *do more actions on **that feedback object** based on the response body.*
            } else {
             feedback.setSent(false); // *do more actions on **that feedback object** based on the response body.*
            }
        }

        @Override
        public void onFailure(@NonNull Call<MyServerResponse> call, @NonNull Throwable t) {
          feedback.setSent(false); // do more actions on **that feedback object** based on the response object.
          Toast.makeText(context,"Hello",Toast.LENGTH_SHORT).show(); // use the passed argument **context**
    });
}

我通过从 for 循环调用上述静态方法,使用 Retrofit 按顺序向服务器发送反馈类型的多个对象。

当试图访问从回调函数内部反馈的传递参数时,IDE 迫使我将传递的参数设为最终参数。

假设:

现在假设每次网络调用都需要 1 秒,直到我收到响应。但是,由于我使用 for 循环来调用 sendFeedback 静态方法,在 Retrofit 回调方法收到第一个响应之前,它会被调用大约 10 次。

问题:由于该方法将在线程通过 Retrofit 异步调用 returns 响应在其内部初始化之前过早结束。这是否意味着在回调方法中完成的工作将在 for 循环中最后传递的 Feedback 类型的参数上,或者在 null 上,因为该方法无论如何都会在那个时候结束?

但是,我确信自从显示使用上下文的 toast 以来,至少有一个传递的参数存在!请给我一个解释。

为什么 IDE 迫使我将论点作为最终论点?

Java 要求如果要在匿名 class 中使用局部变量,它必须是最终的。基本上,任何时候你的代码看起来像

void myMethod(A a, B b) {
    C c = new C();
    doSomething(new MyClass() {
        void methodInAnonymmousClass() {
             a.doSomething();
             c.doSomething();
        }
    });
}

您在匿名 class 中使用的任何局部变量(在本例中为 a 和 c)必须是最终变量。这只是语言的要求。它不会改变您的代码的工作方式。它仍然会按照您期望的方式运行。

首先: 为了从方法内部创建的匿名 class 内部访问任何变量,该变量必须是最终变量。自 Java 8 以来不再需要显式地写 final 关键字,但该变量不得在方法内部更改。所以,毕竟 final 是为你隐式应用的。

其次:每次调用该方法时,该变量都会被复制到匿名class中,以便被创建的匿名classes使用.这就是为什么如果你启动一个线程,它仍然会有变量可以使用,即使方法范围到那时已经结束并且方法参数不再存在。请看下面的代码:

for(int i =0; i<10,i++){
    show(i);
 }

void show(final int param) {
    new Thread(new Runnable() {
        public void run() {
                try {
                    wait(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            System.out.print(param);
        }
    }).start();
}

以上代码将打印:12345678910

相同的概念适用于问题,其中匿名 class 是改造回调。