Java - получить итератор цикла для функции внутри цикла? - PullRequest
4 голосов
/ 14 июня 2011

Вид глупой проблемы, с которой я здесь сталкиваюсь ... По сути, я нахожусь в цикле For, и в этом цикле я всегда вызываю функцию для создания кнопки.Но в этой функции я хочу передать итератор цикла, поскольку он меняется, чтобы различать кнопки.Но потом он говорит мне, что мне нужно сделать итератор цикла "финальным", что означает, что он не меняется!

Что ж, моя проблема станет более понятной с помощью некоторого скелетного кода:

for(int i = 0; i < appList.size(); i++) { 

                //some other stuff including creating the below button 'btn'

                btn.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        //set some attribute based on i
                        //but when I do this it only sets based on the greatest value of i (!)
                    }
                });
}

Мех, глупая проблема, я знаю ... Хотя я новичок в Java!

Приветствия.

Ответы [ 2 ]

4 голосов
/ 14 июня 2011
for(int i = 0; i < appList.size(); i++) { 

    final int _i = i;

    btn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            // use _i instead of i
        }
    });
}
1 голос
/ 14 июня 2011

Рассмотрим этот бит глупого примера кода:

int i = 0;
obj.invokeThunkAfter10Seconds(new ThunkObject() {
    public void thunk() {
        System.out.println(i);
    }
}
i = 1;

ThunkObject содержит ссылку на i, но i может измениться, что делает вывод непредсказуемым и зависит от того, когда i изменяется, и когда вызывается thunk.

Поскольку Java не имеет надлежащих замыканий (по проекту см. Невозможно обратиться к неконечной переменной внутри внутреннего класса, определенного в другом методе), вам явно не разрешено захватывать неконечные (то есть изменяемые) переменные, подобные этой.

Вместо этого вы должны объявить переменную final, то есть она инициализирована и затем не подлежит изменению.Это означает, что вы никогда не сможете изменить i после того, как он был захвачен внутренним классом.

final int i = 0;
obj.invokeThunkAfter10Seconds(new ThunkObject() {
    public void thunk() {
        System.out.println(i);
    }
}
// Can't change i here. It will forever now be 0.

В вашем примере вы не можете просто установить i в качестве окончательного, потому что вы действительно хотите изменитьзначение на каждой итерации цикла.Вместо этого вы можете создать копию значения в конечной переменной:

for(int i = 0; i < appList.size(); i++) { 
    //some other stuff including creating the below button 'btn'

    final int capturedI = i;
    btn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            //set some attribute based on capturedI
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...