Всем привет! Что-то тяжко дается эта тема. Хочется хотя бы приблизительно понять, в чем прикол, так сказать.
Подскажите, пожалуйста, верно ли я поняла суть создания собственных исключений:
Когда мы создаем свой класс, предполагается, что в нем могут быть свойственные этому классу ошибки. Два примера:
1) Когда у нас нет подходящего исключения в уже созданных.
Пример: У нас класс "Семья" и ребенок-школьник может пойти на улицу только, если сделает уроки. И если он идет на улицу, пока дз не выполнено, то мы не можем его пустить. Мы можем сделать это и без исключений, но чтобы у пользователя было понимание, почему действие "прогулка" недоступно, мы можем в классе "Семья" прописать свое собственное исключение, которое будет выводить информацию об ошибки ("Ребенок не может пойти на прогулку, пока ДЗ не выполнено"). Таким образом, с помощью созданного нами исключения наш код стал дружелюбнее к пользователю, хотя особого функционала не прибавилось. И без исключения мы могли бы сделать действие "прогулка" недоступным при несоблюдении всех условий
2) Когда мы хотим сделать уже существующее исключение более понятным для пользователя.
Пример: Допустим, у нас есть компьютерная игра, в которой можно создать всего лишь 12 игроков для своей команды, и мы их всех храним в массиве. Если наш пользователь будет обращаться к 13-му игроку, то наша программа аварийно завершится и кинет исключение. Чтобы этого не было, мы перехватываем исключение про arrayindexoutofboundsexception и вместо него кидаем собственное, в котором пишем сообщение "вы обращаетесь к несуществующему игроку" и предлагаем повторить предыдущий шаг, но уже нормально
Мне кажется, во втором примере есть шероховатости. Потому что я сама пока не совсем понимаю, а почему для этого нам нужны именно собственные исключения, ведь мы могли бы использовать программные, просто в блоке catch писать более человекодружелюбные сообщения на вывод.
В общем, прошу помочь и направить, что я правильно поняла, а в чем очевидно потерялась
Ada
46 уровень
Exception и создание собственных исключений
Решен
Комментарии (12)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Roman Java Developer
5 мая 2022, 22:36решение
Исключения могут содержать не только сообщения, но и кучу всяких других приколюх.
Например, исключения в валидации можно запихнуть массив полей в которых были некорректные данные и к каждой указать что не так, какие там есть условия, что юзер ввел.
Это исключение потом может обработать фронтэнд, показать юзеру что пошло не так, подсветить поля нужные
+2
Ada
6 мая 2022, 04:55
Спасибо за пример! То есть где-то в коде будет заполнение полей юзером, обернутое в try-catch, где в блоке catch будет выбрасывание заранее заготовленного нами ValidationException с вызовом соответствующего метода?
Я пока не дошла до сетевых штук и предположила, что код будет выглядеть как-то так, это оно?
0
Roman Java Developer
6 мая 2022, 09:19полезный
Да, все так
+1
Павел Безумный учёный Expert
5 мая 2022, 21:08
Добавлю ещё такой пример. Положим, у нас имеется программа, выполняющая поиск по электронному каталогу библиотеки. Работает она так: пользователь вводит в консоли какую-то информацию (название книги, имя автора и т. д.), после чего алгоритм формирует запрос к базе данных, получает ответ и выводит его пользователю.
Функционально эту несложную программу можно разделить на три блока:
1) блок ввода-вывода информации от пользователя/пользователю;
2) ядро - внутренняя логика, преобразующая введённые данные в запрос;
3) блок взаимодействия с базой данных - отправляет/ принимает запросы к БД.
В каждом из блоков в процессе работы могут возникать ошибки: например, при вводе некорректных данных, при обрыве соединения с БД, или же какой-нибудь неучтённый разработчиком баг в ядре (случайно поделил на 0 😄). Как Вы правильно заметили, для каждой из этих ошибок желательно иметь свой тип исключения, который бы должным образом описывал конкретную ошибку (это гораздо лучше, чем, к примеру, безликое NullPointerException). Поскольку в каждом функциональном блоке может возникать не одна ошибка, а несколько различных, их неплохо было бы объединить в семейство - и это легко делается при помощи наследования. Такое решение уже позволяет "отлавливать" все "сыпящиеся" исключения на уровне их "родителей", то есть сразу будет понятно, из какого блока "прилетело" то или иное исключение.
0
Павел Безумный учёный Expert
5 мая 2022, 21:08решение
Ошибки также могут быть различного уровня критичности: одни можно просто игнорировать, не беспокоя при этом пользователя (некритические предупреждения); другие также не столь критичны, но требуют участия пользователя (неправильный ввод в консоль); третьи являются критическими, и при их возникновении дальнейшая работа программы невозможна. Такую концепцию также удобно реализовать с помощью наследования, создав иерархию специфических исключений, расширяющих несколько базовых типов, например: InfoException (некритические уведомления), WarningException (предупреждения), CriticalException (критические ошибки).
+2
Ada
6 мая 2022, 04:48
Спасибо за пример! Не знала про существование некритичных исключений, которые можно игнорировать, и в целом не думала, что их можно объединять в иерархию!)
0
Павел Безумный учёный Expert
6 мая 2022, 12:31
Возникающие ошибки могут быть самых разных уровней критичности. В отдельно взятой программе могут возникать свои специфические ошибки, и критерии важности той или иной ошибки определяются разработчиком. В стандартной иерархии исключений Java нет таких общих классов, как "некритические исключения" или "предупреждения". Эти базовые классы (InfoException, WarningException, CriticalException из предыдущего примера) создаются по замыслу разработчика путём наследования от стандартного класса Exception и затем используются для наследования от них классов исключений, описывающих возможные специфические ошибки в программе.
Ещё один момент касательно второго примера, приведенного Вами в тексте вопроса. В общем случае не следует завязывать логику алгоритма на генерировании исключений. Во-первых, выброс исключения - достаточно ресурсоёмкая операция, и их обилие может негативно сказаться на быстродействии всего алгоритма. Во-вторых, само понятие exception предполагает некоторую исключительную ситуацию, то есть то, что не было предусмотрено разработчиком по тем или иным причинам (всего предвидеть невозможно). Другими словами, разработчик должен максимально предусмотреть все возможные нештатные ситуации и обеспечить их обработку явным образом (например, проверка аргумента на null перед вызовом метода, проверка значения индекса в массиве перед обращением к ячейке и т. п.). Когда это сделано, разработчик может обернуть свой код в блок try, как бы говоря таким образом: "Если я ещё что-то не учёл, то пусть эта ошибка будет поймана и я её увижу".
0
Павел Безумный учёный Expert
6 мая 2022, 12:31
Приведу небольшой "антипример":
Здесь показано, как делать не надо. Этот алгоритм делит число a на число b и выводит результат в консоль. Причём число a достаётся из массива ints, а число b считывается с консоли. Во время работы программы могут возникать самые разные ошибки: выход за пределы массива, NPE, ошибка преобразования строки в число, деление на ноль. Исполнительная часть кода обёрнута в try-catch, и на первый взгляд это кажется неплохим решением - мы можем "отлавливать" ошибки и перезапускать алгоритм, пока он не отработает корректно. Но если запустить программу и попробовать ввести число, то в одних случаях мы получим ответ, в других - нет, причём без каких-либо пояснений, что же мы неправильно ввели или почему программа не выдаёт результат и не завершается. 0
milyasow
5 мая 2022, 21:00решение
Примерно да, собственные исключения позволяют конкретизировать проблему, и более того, прописать логику обработки разных исключений, типа, при ArrayIndexOutOfBoundsException выводим одно сообщение, при получении NullPointerException выводим другое сообщение, при третьем - закрываем поток, и т. д.
+2
Ada
6 мая 2022, 04:46
Спасибо! То есть и во втором примере у меня подходящий случай, и зря он меня смущал?
0
milyasow
6 мая 2022, 07:35полезный
Ну, это если в общем случае. Нужно учитывать, что есть нюансы, типа того что Exception должно быть Checked, чтобы их получение не вызывало завершение вашей программы, тогда да, код может выполняться и дальше, если конечно это будет нужно.
+1
Ada
6 мая 2022, 09:00
Спасибо большое!
0