Как обрабатывать ошибку времени выполнения с помощью бросков

В следующем фрагменте кода есть случаи, когда процессы не могут обрабатывать NullPointerException и IllegalStateException. А именно в том случае, когда у меня есть входные значения val=-4 или val=-2.

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

public class Test extends Throwable{
    public static void processA(int val ) throws NullPointerException, IllegalStateException{
        try{
            System.out.println("1");
            processB(val);
        }catch(ArithmeticException e){
            System.out.println("2");
        }
        System.out.println("3");
    }
    public static void processB(int val) throws NullPointerException, IllegalStateException{
        try{
            System.out.println("4");
            processC(val);
        }catch(NullPointerException e){
            System.out.println("5");
            processC(val+4);
        }finally{
            System.out.println("6");
        }
        System.out.println("7");
    }
    public  static void processC(int val)throws NullPointerException, IllegalStateException, ArithmeticException{
        System.out.println("8");
        if(val<1) throw new NullPointerException();
        if(val==1) throw new ArithmeticException();
        if(val>1) throw new IllegalStateException();
        System.out.println("9");
    }

    public static void main(String[] args) throws Exception {
         processA(1); //processA(-2) or processA(-4)
    }

}

person Suslik    schedule 30.01.2019    source источник
comment
Что вы хотите, чтобы код делал, если, скажем, val ‹ 1?   -  person Steve Smith    schedule 30.01.2019
comment
Чего вы пытаетесь достичь? Ваш код будет завершен правильно, только если вы используете 1 в качестве параметра   -  person RKrum    schedule 30.01.2019
comment
В любом случае, вы можете немного почитать о RuntimeExceptions здесь:   -  person RKrum    schedule 30.01.2019
comment
На старом слайде я нашел этот пример, где нужно объяснить, как выглядит поток кода. Также было примечание использовать `throw NullPointerException, IllegalStateException' после подписи метода. Но почему я должен его использовать? Я понимаю, что правильная версия будет использовать несколько блоков catch для обработки всех исключений.   -  person Suslik    schedule 30.01.2019
comment
@Susliks - Но зачем мне его использовать? - Это будет означать, что вызывающему объекту необходимо обработать исключение, созданное этим методом. Теперь вызывающий объект может обработать его с помощью блока try-catch или повторно передать исключение своему вызывающему объекту. Компилятор также выдаст вам сообщение об ошибке, говорящее, что исключение должно быть обработано, но это произойдет только для исключений checked. Те, которые вы выбрасываете, являются непроверенными исключениями. Это означает, что в вашем случае вы можете игнорировать их из объявления метода.   -  person Nicholas K    schedule 30.01.2019


Ответы (2)


Это ломается, потому что вы не обрабатываете сценарий, когда NullPointerException или IllegalStateException выбрасывается в processA(...). Вы обрабатываете только ArithmeticException.

Добавьте следующее в свой код, таким образом, если будет выдано какое-либо из трех исключений, оно будет обработано методом processA.

public static void processA(int val) throws NullPointerException, IllegalStateException {
    try {
        System.out.println("1");
        processB(val);
    } catch (ArithmeticException e) {
        System.out.println("11");
    } catch (NullPointerException e) {
        System.out.println("12");
    } catch (IllegalStateException e) {
        System.out.println("13");
    }
    System.out.println("3");
}

Если вы хотите, чтобы вызывающий объект обрабатывал их, вам нужно сделать то же самое из метода вызывающий. Например:

public static void main(String[] args) {
    try {
        processA(12);
    } catch (ArithmeticException | NullPointerException | IllegalStateException e) {
        // do something here
    } 
}

Чтобы ответить на ваш вопрос в комментариях: "Но зачем мне это использовать?"

Это будет означать, что вызывающая сторона должна будет обработать исключение, созданное этим методом. Теперь вызывающий объект может обработать его с помощью блока try-catch или повторно передать исключение своему вызывающему объекту. Компилятор также выдаст вам сообщение об ошибке, говорящее, что исключение должно быть обработано, но это произойдет только для исключений checked. Выбрасываемые вами исключения являются непроверенными исключениями. Это означает, что в вашем случае вы можете игнорировать их из объявления метода.

person Nicholas K    schedule 30.01.2019

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

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

Использованная литература:

person Rann Lifshitz    schedule 30.01.2019