Доступ к переменной цикла в анонимном классе

Ошибка, которую я получаю, заключается в том, что внутри public void pressedпеременная i не могут быть доступны, если int устанавливается как final, Но если я установлю это как final, i++ становится ошибкой. Я застрял, если я не могу получить доступ к i переменная из моей встроенной функции. Это возможно?

for (int i = 0; i < level.myItems.size(); i++) {
    itemsInInventory[i].setButtonListener(new UIButtonListener() {
        public void pressed(UIButton button, Sprites sprite) {
            itemsInInventory[i].performAction();;
        }
    });
}

2 ответа

Вы можете объявить final локальная переменная внутри цикла:

for(int i = 0; i < level.myItems.size(); i++){
    final int j = i;
    itemsInInventory[i].setButtonListener(new UIButtonListener(){
        public void pressed(UIButton button, Sprites sprite){
            itemsInInventory[j].performAction();
        }
    });
}

Или лучше, так как вам просто нужна кнопка, а не i:

for(int i = 0; i < level.myItems.size(); i++){
    final UIButton btn = itemsInInventory[i];
    btn.setButtonListener(new UIButtonListener(){
        public void pressed(UIButton button, Sprites sprite){
            btn.performAction();
        }
    });
}

Или даже лучше (так как предположительно первый аргумент pressed это сама кнопка):

for(int i = 0; i < level.myItems.size(); i++){
    itemsInInventory[i].setButtonListener(new UIButtonListener(){
        public void pressed(UIButton button, Sprites sprite){
            button.performAction();
        }
    });
}

Обратите внимание, что в последней версии вам не нужно отдельное UIButtonListener для каждой кнопки. Просто установите для них всех одинаковый слушатель, и слушатель автоматически отправит соответствующую кнопку:

UIButtonListener listener = new UIButtonListener(){
    public void pressed(UIButton button, Sprites sprite){
        button.performAction();
    }
};
for(int i = 0; i < level.myItems.size(); i++){
    itemsInInventory[i].setButtonListener(listener);
}

Проблема в том, что время жизни вашей переменной связано с циклом for, но создаваемый вами объект может жить вечно. Чтобы сделать что-то подобное, переменная должна быть конечной, чтобы компилятор знал, что может сделать ее скрытую копию внутри анонимного класса. Вы можете сделать это:

for(int i = 0; i < foo; i++) {
    final int index = i;
    ... anonymous class using "index"...
}

Java 8 делает это немного проще, но доступно только на Android N и новее.

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