Финальный логический [] против финального логического внутри Runnable

Почему разрешено следующее:

final boolean [] success = new boolean[1];
    Thread httpThread = new Thread(new Runnable() {
        @Override
        public void run() {
            HTTPConnect httpConnect = new HTTPConnect(getContext());
            success[0] = false
            ...
            if (whatever)
            success[0] = true;

Но следующего нет?

final boolean success;
    Thread httpThread = new Thread(new Runnable() {
        @Override
        public void run() {
            HTTPConnect httpConnect = new HTTPConnect(getContext());
            success = false
            ...
            if (whatever)
            success = true;

Я имею в виду boolean success Вот. Сначала я думал, что это потому, что локальная декларация потеряет область видимости, в то время как декларация в куче сохранится после окончания области видимости, но это не так, как объявление типа final ArrayList<Foo> bar = new ArrayList<>() не может быть назначено значение.

2 ответа

Решение

Потому что вы на самом деле boolean значение внутри массива, чтобы вы могли изменить содержимое массива, но не изменили ссылку на переменную success сам.

Тот же результат можно получить, используя AtomicBoolean (или же AtomicReference в общем).

Проблема переменных, измененных в анонимных внутренних классах, возникает в следующем сценарии

boolean success;
Thread httpThread = new Thread(new Runnable() {
  @Override
  public void run() {
    success = false;
    ....

Это не разрешено, потому что вы меняете то, что success имеет в виду. Если вы используете boolean[]то ты не меняешь то что есть success ссылаясь только на значение, содержащееся в указанном объекте, поэтому проблем нет.

Прежде всего, ваш второй пример имеет несколько опечаток: так как success это booleanоператоры присваивания не должны быть подписаны.

Я предполагаю, что в обоих случаях success является локальной переменной Если это поле, то вы можете просто устранить final и второй случай будет работать (после устранения подписки).

Причина, по которой второй подход не будет работать для локальной переменной, заключается в том, что вы не можете назначить final переменная после того, как она была назначена. История для массива немного другая: вы все еще не можете назначить новый массив success, но вы можете назначать новые значения элементам массива. Вот почему первый подход работает. Использование такого массива является обычной идиомой для решения как этой проблемы, так и проблемы, связанной с тем, что методы Java не имеют аргументов "out".

Другие вопросы по тегам