繁体   English   中英

给最终变量赋值

[英]Assign a value to a final variable

假设我有以下代码:

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;
}

显然,我无法为onResponseReceived赋值,因为它是最终变量,但如果不是最终变量onResponseReceived,则无法看到它。 然后,如何从onResponseReceived分配一个值作为resp?

我想的是创建一个封装类来封装resp对象。 最终对象将是该包装器类的一个实例,我可以为最终类(不是最终)中的对象分配相应的值。

代码就是这样的:

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;
}

您如何看待该解决方案?

java.util.concurrent.atomic.AtomicReference

标准做法是使用最终的AtomicReference,您可以对其进行设置和获取。 这也增加了线程安全性的好处:)正如您提到的,CountDownLatch在等待完成时很有帮助。

您的解决方案与其他解决方案一样有效。 其他流行的选择包括一个元素数组

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

和通用包装

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

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

您可以使用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();
}

我将进行的更改将使用AtomicReference,因为这显然是多线程的,并且您不必编写自己的包装器。 否则,对我来说似乎很合理。

您可以使其可变且最终;)最简单的方法是使用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];
}

要么

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