Как работают исключения?

88
22 ноября 2020, 01:00
public class DogIsNotReadyException extends Exception {
    public DogIsNotReadyException(String message) {
        super(message);
    }
}
public class Dog {
    String name;
    boolean isCollarPutOn;
    boolean isLeashPutOn;
    boolean isMuzzlePutOn;
    public Dog(String name) {
        this.name = name;
    }
    public void putCollar() {
        System.out.println("Ошейник надет!");
        this.isCollarPutOn = true;
    }
    public void putLeash() {
        System.out.println("Поводок надет!");
        this.isLeashPutOn = true;
    }
    public void putMuzzle() {
        System.out.println("Намордник надет!");
        this.isMuzzlePutOn = true;
    }
    public void walk() throws DogIsNotReadyException {
        System.out.println("Собираемся на прогулку!");
        if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
            System.out.println("Ура, идем гулять! " + name + " очень рад!");
        } else {
            throw new DogIsNotReadyException("Собака " + name + " не готова к прогулке! Проверьте экипировку!");
        }
    }
}

public class Test {
    public static void main(String[] args) throws DogIsNotReadyException {
        Dog dog = new Dog("Rex");
        dog.putCollar();
        dog.putMuzzle();
        dog.walk();
    }
}

Почему вот этот код выводит в консоль:

Ошейник надет!
Намордник надет!
Собираемся на прогулку!
Exception in thread "main" DogIsNotReadyException: Собака Rex не готова к прогулке! Проверьте экипировку!
    at Dog.walk(Dog.java:35)<br>
    at Test.main(Test.java:6)

А вот ниже пример, выводит вот это:

Ошейник надет! 
Намордник надет! 
Собираемся на прогулку! 
Собака Мухтар не готова к прогулке! Проверьте экипировку! 
Проверяем снаряжение! Ошейник надет? true
Поводок надет? false 
Намордник надет? true 

Вот пример:

public class DogIsNotReadyException extends Exception {
    public DogIsNotReadyException(String message) {
        super(message);
    }
}

public class Dog {
    String name;
    boolean isCollarPutOn;
    boolean isLeashPutOn;
    boolean isMuzzlePutOn;
    public Dog(String name) {
        this.name = name;
    }
    public void putCollar() {
        System.out.println("Ошейник надет!");
        this.isCollarPutOn = true;
    }
    public void putLeash() {
        System.out.println("Поводок надет!");
        this.isLeashPutOn = true;
    }
    public void putMuzzle() {
        System.out.println("Намордник надет!");
        this.isMuzzlePutOn = true;
    }
    public void walk() throws DogIsNotReadyException {
        System.out.println("Собираемся на прогулку!");
        if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
            System.out.println("Ура, идем гулять! " + name + " очень рад!");
        } else {
            throw new DogIsNotReadyException("Собака " + name + " не готова к прогулке! Проверьте экипировку!");
        }
    }
}
public class Test {
    public static void main(String[] args)  {
        Dog dog = new Dog("Rex");
        dog.putCollar();
        dog.putMuzzle();
        try{
            dog.walk();
        } catch (DogIsNotReadyException e) {
            System.out.println(e.getMessage());
            System.out.println("Проверяем снаряжение! \n Ошейник надет? " + dog.isCollarPutOn + "\r\n Поводок надет? "
                    + dog.isLeashPutOn + "\r\n Намордник надет? " + dog.isMuzzlePutOn);
        }
    }
}

Вопросы:

  1. Почему первый пример не работает если мы метод main помечаем throws? Должно же одинаково отрабатывать как с первым примером так и со вторым. Ну либо throws либо try catch должно быть.

  2. Не понимаю как отрабатывает метод getMessage(), залез в исходники и увидел вот это:

    public String getMessage() {
        return detailMessage;
    }
    

    Посмотрел что такое detailMessage это просто переменная, не очень всё равно понял как это отрабатывает. Для проверки сделал вот так:

    public class Test {
        public static void main(String[] args)  {
            Dog dog = new Dog("Rex");
            try{
                dog.walk();
            } catch (DogIsNotReadyException e) {
                System.out.println(e.getMessage());
            }
        }
    }
    

    Вывелось в консоль:

    Собираемся на прогулку!
    Собака Rex не готова к прогулке! Проверьте экипировку!
    

    В вызове метода walk отрабатывает

    System.out.println("Собираемся на прогулку!");
    

    А вот потом отрабатывает throw new DogIsNotReadyException("Собака " + name + " не готова к прогулке! Проверьте экипировку!"); но только когда System.out.println(e.getMessage()); мы написали, не понимаю как отрабатывает код.

Answer 1

Примеры работают.

Исключение необходимо ловить, иначе оно выбрасывается выше, на уровень управляющего кода.

Это справедливо и для функции main

В первом примере вы его пробрасываете наружу

public static void main(String[] args) throws DogIsNotReadyException {

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

ОС узнает об исключении и может предпринять действия по его обработке.

Представьте что Ваша программа по выгулу собак часть чего-то большего. Управляющий код так же должен узнать о нештатных ситуациях и уметь например перезапустить Вашу программу.

PS: getMessage это метод акцессор для поля message у исключения, оно выводит строку, которая была передана в конструктор исключения и там запомнена в переменную message

READ ALSO
Ошибка ClassNotFoundException в методе readObject()

Ошибка ClassNotFoundException в методе readObject()

Мне надо десериализовать объекты в список, но у меня вылазит ошибка

118
Посоветуйте пожалуйста хороший курс по javafx [дубликат]

Посоветуйте пожалуйста хороший курс по javafx [дубликат]

Посоветуйте пожалуйста хороший курс(или канал, или книгу

85
Обработка windowClosing JFrame

Обработка windowClosing JFrame

решил сделать возможность обработки закрытия окна через "крестик"

96