Бесконечная рекурсия в Java?

Очевидно, следующая рекурсия в Java вызовет ошибку переполнения стека:

public class XXX {
    public static void main(String[] args) {
        main(null);
    }
}

Но что, если я поймаю эту ошибку и снова вызову функцию?

public class XXX {
    public static void main(String[] args) {
        try {
            main(null);
        } catch(StackOverflowError E) {
            main(null);
        }
    }
}

как это работает тогда ??

Почему бы тебе не попробовать?

user7 08.06.2018 17:53

Сообщите нам, каков результат

GalAbra 08.06.2018 17:53

Ну, я пробовал это несколько раз, и это дало мне бесконечную рекурсию ...

Bo Wang 08.06.2018 17:54

Но действительно ли это разрешено в реальной программе?

Bo Wang 08.06.2018 17:55

@BoWang Почему бы и нет? Я полагаю, вы все равно будете бросать StackOverflowException, пока не израсходуете всю доступную память в куче.

Mapsy 08.06.2018 17:55

Разве у вас не настоящая программа?

user7 08.06.2018 17:56

Хмммм не знаю. но поскольку это вызывает ошибку, я чувствую, что в этом типе рекурсии есть некоторые ограничения.

Bo Wang 08.06.2018 17:56

На самом деле это не сработает. Потому что второй вызов внутри try/catch не является try/catch. ;)

Mapsy 08.06.2018 17:57

@AlexT. Он пойман, но на один уровень выше в стеке, он в конечном итоге закончится, но если стек разрешает вызовы n, я думаю, что это вызовет вызовы 2^n до того, как вызов верхнего уровня в main внутри улова верхнего уровня, наконец, выбросит и заставит программу выход.

Paul 08.06.2018 17:58

Я не знаю этого, и у меня нет никаких доказательств этого, но я предполагаю, что если бы кто-то совершил такое очевидное злоупотребление практикой программирования, то результат был бы зависящим от платформы.

Chris Parker 08.06.2018 17:59

lol "злоупотребление" настолько точным

Bo Wang 08.06.2018 18:02

@BoWang Я бы порекомендовал почитать о том, почему нельзя ловить Error

Jaroslaw Pawlak 08.06.2018 18:11

Вот пример проблемы, связанной с платформой, которая может возникнуть. Поскольку вашей программе будет постоянно не хватать памяти, это может создать проблему в системном потоке, где в конечном итоге она не сможет выполнять некоторые критические функции из-за того, что вся доступная память будет уничтожена. Затем через какой-то непредсказуемый интервал ошибка может быть чем-то другим, кроме StackOverflowError. Я просто размышляю, потому что не знаю, насколько строго JVM определяет этот тип деталей реализации. Короче говоря, отлов StackOverflowError почти всегда - плохая идея.

Patrick Parker 08.06.2018 18:16

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

EJoshuaS - Reinstate Monica 08.06.2018 19:40
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
14
452
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Программа в конечном итоге остановится, потому что вызов main(null) в блоке catch снова не перехватывает StackOverflowError. StackOverflowError в конечном итоге будет распространяться вниз по стеку.

Вы можете увидеть это, уменьшив размер стека с помощью опции -Xss108k JVM (наименьшее возможное значение на моей JVM) и изменив программу, чтобы выделить как можно больше в стеке, например. с использованием локальных переменных double:

public static void main(String... args) {
  try {
    double a00 = 0.13;
    double a01 = 0.13;
    ...
    double a99 = 0.13;
    double b00 = 0.13;
    double b01 = 0.13;
    ...
    double k99 = 0.13;

    main(null);
  } catch (StackOverflowError ex) {
    main(null);
  }
}

Это приводит к тому, что StackOverflowError генерируется после 5 рекурсивных вызовов, и программа завершается.

Это не так много смысла, как бесконечный цикл, и это не очень хорошая идея. Если main вызвал что-либо еще, что могло бы вызывать другие методы, он будет вызывать случайные точки внутри main на каждой итерации в зависимости от глубины стека вызовов при запуске этого вызова main. В конечном итоге он также перестанет повторяться из-за того, что заметил @Alex T., хотя он будет работать очень долго.

Paul 08.06.2018 18:02

@Paulpro спасибо, что указали на это, вы правы.

Karol Dowbecki 08.06.2018 18:38

Нет проблем, хорошая демонстрация.

Paul 08.06.2018 18:53

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