Java не проверено / проверено уточнение исключения

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

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

Мой вопрос, предположим, ради аргумента у меня есть метод, который делит два числа

double divide(double numerator, double denominator)
{    return numerator / denominator;    }

и метод, который требует где-то отдел

void foo()
{    double a = divide(b, c);    }

Кто отвечает за проверку случая, когда знаменатель равен нулю, и следует ли проверять или снимать исключение (игнорируя встроенные проверки деления в Java)?

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

double divide(double numerator, double denominator) throws DivideByZeroException
{
    if(denominator == 0) throw DivideByZeroException
    else ...
}

void foo()
{
    try{
        double a = divide(b, c);
    }
    catch(DivideByZeroException e)
    {}
}

или без проверенного исключения, как:

double divide(double numerator, double denominator)
{
    if(denominator == 0) throw DivideByZeroException
    else ...
}

void foo()
{
    if(c != 0)
       double a = divide(b, c);
}

и позволить foo проверить деление на ноль?

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

6 ответов

Решение

Действительно интересная тема!

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

Ошибки программиста никогда не должны быть пойманы, а скорее сбой (!) Рано и сильно. Ошибка программиста связана с логической ошибкой, и основная причина должна быть исправлена.

Ожидаемые ошибки всегда должны быть обнаружены. Также, когда ожидаемая ошибка обнаружена, сообщение должно быть отображено для пользователя. Это имеет важное значение: если ожидаемая ошибка не должна отображать ошибку, лучше проверить, будет ли метод генерировать метод, а не давать ему генерировать метод.

Применительно к вашему примеру я подумаю: "Как это должно выглядеть для пользователя?"

  1. Если должно отображаться сообщение об ошибке (в выходных данных браузера, консоли, окне сообщений), я выбрасываю исключение и перехватываю его как можно ближе к интерфейсу пользователя, и выводю сообщение об ошибке.
  2. Если сообщение об ошибке не отображается, я бы проверил ввод и не выбросил.

По sidenote: я никогда не бросаю DivideByZeroException ни NullPointerException - Я позволил JVM бросить это для меня. В этом случае вы можете создать свой собственный класс исключений или использовать подходящее встроенное проверенное исключение.

Предположим, что проверенное исключение выдается в результате математической операции. Например, разделение (согласно вашему сообщению).
Это будет означать, что каждое целочисленное деление должно появляться в блоке try!
На самом деле деление может вызвать исключение ArithmeticException, которое является непроверенным исключением, поэтому нет необходимости его перехватывать.
На самом деле вы не должны его ловить, так как это исключительное условие, которое возникает и обычно может быть решено только путем исправления кода.
В вашем случае ваш код должен был что-то сделать до фактического деления на ноль.
Если вы достигли шага, на котором вы фактически разрешаете деление на ноль, то вы ничего не можете сделать. Программа ошибочна, и ее лучше исправить, чем пытаться каким-то образом замаскировать ее, выдав / поймав исключение

Моя любимая дискуссия о разнице в философии между проверенными и непроверенными исключениями в Java:

http://www.javapractices.com/topic/TopicAction.do?Id=129

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

  • java.lang.Exception - известный как проверенные исключения
  • java.lang.RuntimeException известный как UNchecked исключения - в качестве бонуса java.land.RuntimeException расширяет java.lang.Exception (для облегчения обработки в catch блоки и не только)
  • java.lang.Error - ошибки, которые также не проверяются и редко требуются для обработки кодом пользовательского пространства, но знание их и их отклонений является существенным плюсом. К ним относятся (наиболее известные): ошибка компоновки, переполнение стека, нехватка памяти, ошибки утверждения
  • java.lang.Throwable - Проверено! и мать всех исключений, немногие должны непосредственно подклассить это, но некоторые делают по неизвестным причинам

Поэтому необходимо объявить исключения и позаботиться о правильном распространении (только на уровне компиляции), непроверенные распространяются автоматически, и от разработчика не ожидается, что он будет обрабатывать их, если в этом нет необходимости.

Проверенные, как правило, ожидаются и требуют дополнительного многословия в Java, уже пушистом коде.

Худшие практики включают в себя: catch (Throwable t){}По многим причинам ошибки обычно не обрабатываются, если в этом нет необходимости, и большинство ошибок обычно приводят к смерти потока в любом случае.

Никогда не бросайте явно RuntimeExceptions. Если вы когда-либо думали, что вам нужно, просто дайте времени выполнения сделать это, а не использовать throw,

Короткий ответ, так как некоторые плюсы и минусы были названы: это вопрос личного или организационного стиля. Ни один из них функционально не лучше другого. Вы (или ваш проект) должны будете сами принять решение о том, использовать ли проверенные или непроверенные исключения, или и то, и другое.

Oracle Java Tutorial советует вам использовать проверенные исключения для всех ошибок, из которых приложение может восстановиться, и непроверенные исключения для ошибок, из которых приложение не может восстановиться. Но по моему опыту большинство приложений могут восстановиться после большинства (может быть, не во время запуска) исключений. Неудачное действие будет прервано, но приложение останется активным.

Я бы предпочел использовать только проверенные или непроверенные исключения. Смешивание может привести к путанице и непоследовательному использованию. Будьте прагматичны. Делайте то, что имеет смысл в вашей ситуации.

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