Различное поведение при перехвате Throwable и StackOverflowError

У меня есть два следующих набора кода

Первый набор кода выглядит следующим образом:

public static void main(String[] args){
    try {
        main(null);
    } catch (Throwable e) {
    }

    System.out.println("Value of args[0] is : "args[0]);
}

Выход:

Value of args[0] is : db

Второй набор кода выглядит следующим образом:

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

    }

    System.out.println(args[0]);
}

Выход:

Exception in thread "main" java.lang.NullPointerException
at com.way2learnonline.ui.Demo.main(Demo.java:16)

В обоих случаях я передаю аргумент командной строки, то есть «db». В первом наборе кода я ловлю Throwable в блоке catch, где я могу получить доступ к аргументу командной строки, то есть args[0] (я вижу вывод args[0] в консоли).

Во втором наборе кода я ловлю StackOverflowError, где я не могу получить доступ к аргументам [0]. Он показывает исключение NullPointerException.

Я не могу понять поведение Java.

Почему я могу получить доступ к args[0] в первом случае и почему args имеет значение null во втором случае.

Может кто-нибудь объяснить, почему Java ведет себя так?


person Jagadeesh    schedule 17.08.2015    source источник
comment
Обратите внимание, что ловить StackOverflowError в реальных проектах — крайне плохая практика.   -  person Tagir Valeev    schedule 17.08.2015


Ответы (2)


StackOverflowError произойдет в обоих фрагментах кода.

Код, перехватывающий StackOverflowError, обработает его при последнем рекурсивном вызове метода, но поскольку catch ничего не делает, будет выполнена следующая строка кода:

System.out.println(args[0]);

И это выдаст NullPointerException, так как args это null и вы не можете получить доступ к args[0].

Другой будет обрабатывать каждую ошибку или исключение, включая этот NullPointerException, и будет проходить через все методы в вызове, поэтому выполнение кода будет продолжаться. Похоже, вы передаете в качестве аргумента "db", так что это то, что печатается.

person Luiggi Mendoza    schedule 17.08.2015

В первом случае вы перехватываете все исключения, поэтому, когда вы вызываете main с нулевым значением args, результирующее NullPointerException перехватывается, и вы его не видите.

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

Похоже, вы просто экспериментируете, но стоит сказать, что вы никогда не должны ловить StackOverflowError в «настоящем» коде.

person codebox    schedule 17.08.2015