2012-12-12 4 views
1

Предположим, что у меня есть этот код:Присвоить значение конечной переменной

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. Конечным объектом будет экземпляр этого класса-оболочки, и я мог бы присвоить значение, действующее на объект внутри конечного класса (что не является окончательным).

код будет такой:

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

Что вы думаете об этом решении?

+0

Прежде всего, это работает? Вы попробовали это, чтобы увидеть результат? –

+0

Да, это работает, но я не знаю, является ли это хорошим способом решения этой общей проблемы. – Massimo

+0

Тогда это, вероятно, лучший пост для http://codereview.stackexchange.com/ –

ответ

6

java.util.concurrent.atomic.AtomicReference

Стандартная практика заключается в использовании окончательного AtomicReference, который вы можете установить и получить. Это также добавляет преимущества безопасности потоков. Как вы уже упоминали, функция CountDownLatch полезна в ожидании завершения.

+0

Спасибо! Эта практика, безусловно, лучше, чем моя :) спасибо также всем остальным, все полезные ответы! – Massimo

0

Изменение, которое я бы сделал, было бы использовать AtomicReference, поскольку это, очевидно, многопоточность, и вам не придется писать свою собственную оболочку. В противном случае мне кажется разумным.

4

Ваше решение так же эффективно, как и любое другое. Другие популярные варианты включают в себя массив один элемент

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

Вы можете сделать это изменчивым и окончательным;) Самый простой подход заключается в использовании на массив но 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(); 
} 
1

Вы можете комбинировать ручной спиной и ждать в одну, используя (обработка исключений опущена) в 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(); 
} 
Смежные вопросы