简体   繁体   English

给最终变量赋值

[英]Assign a value to a final variable

Suppose I have this code: 假设我有以下代码:

public HttpResponse myFunction(...) {
    final HttpResponse resp;
    OnResponseCallback myCallback = new OnResponseCallback() {
        public void onResponseReceived(HttpResponse response) {
            resp = response;
        }
    };
    // launch operation, result will be returned to myCallback.onResponseReceived()
    // wait on a CountDownLatch until operation is finished
    return resp;
}

Obviously I can not assign a value to resp from onResponseReceived because it is a final variable, BUT if it was not a final variable onResponseReceived could not see it. 显然,我无法为onResponseReceived赋值,因为它是最终变量,但如果不是最终变量onResponseReceived,则无法看到它。 Then, how can I assign a value to resp from onResponseReceived? 然后,如何从onResponseReceived分配一个值作为resp?

What I thought is to create a wrapper class for enclosing the resp object. 我想的是创建一个封装类来封装resp对象。 The final object would be an instance of this wrapper class and I could assign the value to resp working on the object inside the final class (which is not final). 最终对象将是该包装器类的一个实例,我可以为最终类(不是最终)中的对象分配相应的值。

The code would be this one: 代码就是这样的:

class ResponseWrapper {
    HttpResponse resp = null;
}

public HttpResponse myFunction(...) {
    final ResponseWrapper respWrap = new ResponseWrapper();
    OnResponseCallback myCallback = new OnResponseCallback() {
        public void onResponseReceived(HttpResponse response) {
            respWrap.resp = response;
        }
    };
    // launch operation, result will be returned to myCallback.onResponseReceived()
    // wait on a CountDownLatch until operation is finished
    return respWrap.resp;
}

What do you think about this solution? 您如何看待该解决方案?

java.util.concurrent.atomic.AtomicReference java.util.concurrent.atomic.AtomicReference

Standard practice is to use a final AtomicReference, which you can set and get. 标准做法是使用最终的AtomicReference,您可以对其进行设置和获取。 This adds the benefit of thread safety as well :) As you mentioned, a CountDownLatch is helpful in waiting for completion. 这也增加了线程安全性的好处:)正如您提到的,CountDownLatch在等待完成时很有帮助。

Your solution is as valid as any other. 您的解决方案与其他解决方案一样有效。 Other popular choices include the one element array 其他流行的选择包括一个元素数组

final HttpResponse[] resp = new Response[1];
// In the callback
resp[0] = response;
// After the operation
return resp[0];

and the generic wrapper 和通用包装

public class Ref<T> {
  public T value;
}

final Ref<HttpResponse> resp;
// In the callback
resp.value = response;
// After the operation
return resp.value;

You can combine the hand-back and the wait into one using a SynchronousQueue (exception handling omitted) 您可以使用SynchronousQueue将递归和等待合并为一个(省略了异常处理)

public HttpResponse myFunction(...) {
    final Queue<HttpResponse> resp = new SynchronousQueue<HttpResponse>();
    OnResponseCallback myCallback = new OnResponseCallback() {
        public void onResponseReceived(HttpResponse response) {
            resp.put(response);
        }
    };
    return resp.take();
}

The change I would make would be to use an AtomicReference since this is obviously multi-threaded and you wouldn't have to write your own wrapper. 我将进行的更改将使用AtomicReference,因为这显然是多线程的,并且您不必编写自己的包装器。 Otherwise, seems reasonable to me. 否则,对我来说似乎很合理。

You can make it mutable and final ;) The simplest approach is to use na array but an AtomicReference can also be used. 您可以使其可变且最终;)最简单的方法是使用na数组,但也可以使用AtomicReference。

public HttpResponse myFunction(...) {
    final HttpResponse[] resp = { null };
    OnResponseCallback myCallback = new OnResponseCallback() {
        public void onResponseReceived(HttpResponse response) {
            resp[0] = response;
        }
    };
    // launch operation, result will be returned to myCallback.onResponseReceived()
    // wait on a CountDownLatch as soon as operation is finished
    return resp[0];
}

or 要么

public HttpResponse myFunction(...) {
    final AtomicReference<HttpResponse> resp = new AtomicReference<HttpResponse>();
    OnResponseCallback myCallback = new OnResponseCallback() {
        public void onResponseReceived(HttpResponse response) {
            resp.set(response);
        }
    };
    // launch operation, result will be returned to myCallback.onResponseReceived()
    // wait on a CountDownLatch as soon as operation is finished
    return resp.get();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM