Страницы

Поиск по вопросам

четверг, 8 ноября 2018 г.

Проверяемые исключения

Пусть есть метод, который может бросить проверяемое исключение при некорректных входных параметрах
void throwMethod(int count) throws MyException { if (count < 0) throw new MyException(...); ....... }
и есть вызывающий метод, который передает гарантировано правильный параметр
void callMethod() { int count = 15; throwMethod(count); }
Компилятор говорит, что callMethod должен декларировать возможность возникновения исключения MyException. Т.е. у меня есть два пути: либо задекларировать это
void callMethod() throws MyException { int count = 15; throwMethod(count); }
либо поймать его
void callMethod() { int count = 15; try { throwMethod(count); } catch (MyException e) {} }
первый вариант мне не нравится, т.к. декларируется событие, которое никогда не произойдет. Во втором варианте закапываются грабли, которые могут всплыть при рефакторинге. Скажем, в методе throwMethod усилится проверка
void throwMethod(int count) throws MyException { if (count < 0 && count > 10) throw new MyException(...); ....... }
или вызываемый метод перепишется
void callMethod() { int count = 15 - List.count; try { throwMethod(count); } catch (MyException e) {} }
тогда исключение потеряется и ошибку придется искать долго. Ну и кроме того, у меня стабильное отвращение перед пустой catch секцией.
Есть еще мысль, выбросить непроверяемое исключение
void callMethod() { int count = 15; try { throwMethod(count); } catch (MyException e) { throw new RuntimeException(e); } }
Тогда если сейчас исключений не может быть, тогда и RuntimeException не будет. А если что-то поменяется, то хоть ошибку увидим. Но это попахивает каким-то костылем.
Вопрос - как делать правильно?
UPDATE
Вопрос возник по мотивам конструктора класса URL(String), который может бросить MalformedURLException если в строке не указан протокол, указан неизвестный протокол или передан null. И я создаю объект кодом
URL url = new URL('http://google.com/');


Ответ

} catch (MyException e) { throw new RuntimeException(e); }
Так делать не красиво. Если вы допускаете что исключение лучше сделать рантайм, то сделайте свое исключение, которое будет расширять RuntimeException
} catch (MyException e) {}
Так делать определенно очень, очень плохо. Как вы правильно рассуждали, могут быть трудновыловимые баги. Так что, по моему опыту, лучше уж кропотливо обрабатывать все ошибки, даже если вам кажется что они возникнуть не могут. Ну тут я бы сделал примерно так:
void callMethod() throws MyException {/* ... */}
А уже в методе, который делает ряд вычислений, включая вызов callMethod(), я бы сделал ряд блоков try/catch, в которых бы обрабатывались разные варинты исключительных ситуаций. примерно так:
try { /* ряд методов и вычсилений */ } catch (MyException1 e1) { //обработка одного из исключений } catch (MyException me) { //обработка вашего исключения. } catch (Exception e) { //на всякий случай, если произойдет совсем неожиданное исключение }

Комментариев нет:

Отправить комментарий