Java: как избежать StackOverflowException
Я пишу функцию, которая будет называть себя примерно до 5000 раз. Конечно, я получаю исключение StackOverflowException. Есть ли способ, чтобы я мог переписать этот код довольно простым способом:
void checkBlocks(Block b, int amm) {
//Stuff that might issue a return call
Block blockDown = (Block) b.getRelative(BlockFace.DOWN);
if (condition)
checkBlocks(blockDown, amm);
Block blockUp = (Block) b.getRelative(BlockFace.UP);
if (condition)
checkBlocks(blockUp, amm);
//Same code 4 more times for each side
}
Кстати, каково ограничение того, насколько глубоко мы можем назвать функции?
Спасибо!
Ответы
Ответ 1
Возможно использование стека?
void checkBlocks(Block b, int amm) {
Stack<Block> blocks = new Stack<Block>();
blocks.push(b);
while (!blocks.isEmpty()) {
b = blocks.pop();
Block blockDown = (Block) b.getRelative(BlockFace.DOWN);
if (condition)
blocks.push(block);
Block blockUp = (Block) b.getRelative(BlockFace.UP);
if (condition)
blocks.push(block);
}
}
Ответ 2
размер стека по умолчанию в java равен 512kb. если вы превысите эту программу, прекратите метать StackOverflowException
вы можете увеличить размер стека, передав аргумент JVM:
-Xss1024k
теперь размер стека равен 1024kb. вы можете дать более высокое значение на основе вашей среды
Я не думаю, что мы можем программно изменить это
Ответ 3
Размер стека можно увеличить с помощью -Xss4m.
Ответ 4
Вы можете поместить свой "Блок" в очередь/стек и итерации до тех пор, пока доступны блоки.
Ответ 5
Очевидно, что вы получаете StackOverflow с таким коэффициентом ветвления вашей рекурсии. На других языках можно достичь с помощью оптимизации Tail Call Optimization. Но я полагаю, что ваша проблема нуждается в другом способе решения.
В идеале вы выполняете некоторую проверку блока. Может быть, вы можете получить список всех блоков и проверить каждый из них итеративно?
Ответ 6
В большинстве случаев рекурсия используется неверно. Вы не должны получать исключение стека за потоком.
У вашего метода нет возвращаемого типа/значения.
Как вы гарантируете, что ваш начальный блок b действителен?
Если вы используете рекурсию, задайте себе следующий вопрос:
- Что такое мой рекурсивный якорь (когда я останавливаюсь с рекурсией)
- Что такое мой шаг рекурсии (как уменьшить количество вычислений)
Пример:
мой рекурсивный якорь равен n == 2 (результат равен 2), поэтому я могу рассчитать все результаты, начинающиеся с этого якоря.
мой шаг рекурсии n-1 (так что каждый шаг я приближаюсь к решению (и в этом случае к моему рекурсивному якорю))