Не могу передать объект в лямбда-выражение. Ошибка: error: local variables referenced from a lambda expression must be final or effectively final

346
20 сентября 2017, 11:05

Имеется цикличное создание и отображение кнопок. Каждая кнопка,по нажатию, должна передавать в функцию саму себя.

for (int i = 0; i <= 6; i++) {
    for (int j = 0; j <= 17; j++) {
        Cell[i][j] = createButton((ArenaLine.getMaxWidth() / 20) * 1, (ArenaLine.getMaxHeight() / 9) * 1, (ArenaLine.getMaxWidth() / 20) * (j + 1), (ArenaLine.getMaxHeight() / 9) * (i + 1));
        ArenaLine.getChildren().add(Cell[i][j]);
        Cell[i][j].setOnAction((ActionEvent actionEvent) -> {
            Spawn(Cell[i][j]);
        });
    }
}

Проблема заключается в том,что i и j — локальные переменные, и функция выдает следующую ошибку на строке Spawn(Cell[i][j]);:

error: local variables referenced from a lambda expression must be final or effectively final Spawn(Cell[i][j]);

Загвоздка в том, что я не могу передать конкретную ссылку на конкретную кнопку из-за изменчивости i и j.
Конечно, можно прописать для каждого элемента действие отдельно,но элементов в массиве крайне много.
Какие есть выходы из данной ситуации? Что можно тут придумать?

Answer 1

Довольно топорно, но:

for (int i = 0; i <= 6; i++) {
    for (int j = 0; j <= 17; j++) {
        Cell[i][j] = createButton((ArenaLine.getMaxWidth() / 20) * 1, (ArenaLine.getMaxHeight() / 9) * 1, (ArenaLine.getMaxWidth() / 20) * (j + 1), (ArenaLine.getMaxHeight() / 9) * (i + 1));
        ArenaLine.getChildren().add(Cell[i][j]);
        final int ii = i;
        final int jj = j;
        Cell[ii][jj].setOnAction((ActionEvent actionEvent) -> {
            Spawn(Cell[ii][jj]);
        });
    }
}

или

for (int i = 0; i <= 6; i++) {
    for (int j = 0; j <= 17; j++) {
        final Button button = createButton((ArenaLine.getMaxWidth() / 20) * 1, (ArenaLine.getMaxHeight() / 9) * 1, (ArenaLine.getMaxWidth() / 20) * (j + 1), (ArenaLine.getMaxHeight() / 9) * (i + 1));
        Cell[i][j] = button; 
        ArenaLine.getChildren().add(button);
        button.setOnAction( ae -> {
            Spawn(button);
        });
    }
}

P.S. Не пишите имена переменных и методов с заглавной буквы, так не принято в java.

Answer 2

Компилятор вам сказал, что нельзя использовать не финальные переменные в лямбдах. Так, что либо не используйте примитивы, либо не используйте лямбду(сделайте анонимным классом)

READ ALSO
Java + Steam авторизация

Java + Steam авторизация

есть ли возможность реализовать авторизацию в моем приложении через steam? Знаю о Steam Web Api но это только для веб сайтов, на сколько я понимаю

231
Unable to add window- Android ошибка

Unable to add window- Android ошибка

У меня из багтрекера переодически приходит ошибка с таким трейсомКто нибудь может подсказать в чем может быть проблема? Использую Activity и несколько...

267
Задача на округление чисел в Java

Задача на округление чисел в Java

Нужно написать метод, который получает на вход 4 дробных положительных числа, сумма которых является целым числом, а возвращает 4 целых числа...

486
Как скачивать и сохранять изображения в память телефона?

Как скачивать и сохранять изображения в память телефона?

Моя задача: спарсить JSON из интернета, положить их в SQLite (это я сделал), но я сохранил только пути к изображению, но не сами изображенияМне нужно...

259