Пример создания исключения java

Создание своих исключений

Думаю, тебе уже доводилось сталкиваться с ситуацией, когда запускаешь код, а в результате получаешь что-то вроде NullPointerException , ClassCastException или что похуже. Потом долгая отладка, разбор, гугление и так далее. Сами по себе исключения — отличная штука: они указывают, где возникла проблема и какого рода. Если хочешь освежить память, да и просто узнать подробнее, загляни в статью Исключения: checked, unchecked и свои собственные (javarush.ru)

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

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

 public class PhoneNumberIsExistException extends Exception < public PhoneNumberIsExistException(String message) < super(message); >> 

Следом используем его для проверки:

 public class PhoneNumberRegisterService < ListregisteredPhoneNumbers = Arrays.asList("+1-111-111-11-11", "+1-111-111-11-12", "+1-111-111-11-13", "+1-111-111-11-14"); public void validatePhone(String phoneNumber) throws PhoneNumberIsExistException < if (registeredPhoneNumbers.contains(phoneNumber)) < throw new PhoneNumberIsExistException("Указанный номер телефона уже используется другим клиентом!"); >> > 

Для упрощения задачи мы “захардкодим” несколько номеров телефонов — пусть это будет наша база данных. Ну и, наконец, попробуем применить наше исключение:

 public class CreditCardIssue < public static void main(String[] args) < PhoneNumberRegisterService service = new PhoneNumberRegisterService(); try < service.validatePhone("+1-111-111-11-14"); >catch (PhoneNumberIsExistException e) < // здесь можно сделать запись в логи или вывод стека вызовов e.printStackTrace(); >> > 

Ну что, пора нажать Shift+F10 (если используешь IDEA), то есть, запустить проект. И вот что ты увидишь в консоли:

Читайте также:  Open window function html

exception.CreditCardIssue
exception.PhoneNumberIsExistException: Указанный номер телефона уже используется другим клиентом!
at exception.PhoneNumberRegisterService.validatePhone(PhoneNumberRegisterService.java:11)

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

Добавь еще одно: например, для проверки наличия букв. Как ты наверняка знаешь, в США часто используют буквы для упрощения запоминания номера, вроде 1-800-MY-APPLE. То есть, тебе надо проверить, чтобы в номере были только цифры.

Итак, мы создали проверяемое, то есть,

Сообщество программистов разделилось на два лагеря — те, кто за проверяемые исключения и те, кто против. Обе стороны приводят веские аргументы. Среди тех и других есть разработчики экстра-класса: Брюс Эккель критикует концепцию проверяемых исключений, Джеймс Гослинг защищает. Похоже, этот вопрос никогда не будет окончательно закрыт. Тем не менее, давайте рассмотрим основные минусы использования проверяемых исключений.

Главный минус проверяемых исключений — их надо обрабатывать. И тут у нас два варианта: либо обрабатывать на месте, используя try-catch , либо, если у нас одно и то же исключение используется во многих местах, пробрасывать с помощью throws выше, и в классах верхнего уровня их обрабатывать.

Также у нас может возникнуть “простыня” кода, или как иногда можно услышать — boilerplate, то есть много кода, который места занимает много, но смысловой нагрузки несет мало.

Проблемы начинаются в достаточно больших приложениях: обрабатываемых исключений становится много, и метод верхнего слоя легко может обрасти списком throws с десятком исключений.

public OurCoolClass() throws FirstException, SecondException, ThirdException, ApplicationNameException.

Часто разработчикам это не нравится, и они идут на хитрость: наследуют все свои проверяемые исключения от одного предка — ApplicationNameException . Теперь они обязаны ловить в обработчике еще и его ( checked же!):

 catch(FirstException e) < // todo >catch(SecondException e) < // todo >catch(ThirdException e) < // todo >catch(ApplicationNameException e) < // todo >

Тут нас ждет еще одна проблема: а что делать в последнем catch ? Выше мы уже обработали все штатные ситуации, которые предусмотрели, но здесь ApplicationNameException для нас значит не больше, чем Exception : “какая-то непонятная ошибка”. Так и обрабатываем:

 catch(ApplicationNameException e)

И в итоге мы не знаем, что произошло.

Но, казалось бы, можно же все прокинуть одним движением руки:

 public void ourCoolMethod() throws Exception < // do some >

Да, можно. Но какую информацию несет “throws Exception”? Что-то сломалось. Придется проверять все от и до, и ты надолго подружишься с дебагером, чтобы понять причину.

Еще ты можешь встретить конструкцию, которую иногда называют “поймал — молчи”:

Тут не нужно лишних слов — по коду все понятно, а точнее — ничего не понятно.

Конечно, ты можешь возразить, что такое не встретишь в реальном коде. Хорошо, давай посмотрим такую штуку, как класс URL из пакета java.net и заглянем в ее недра, в ее код. Follow me if you want to know!

Вот один из конструкторов URL :

 public URL(String spec) throws MalformedURLException

Как видишь, тут есть интересное проверяемое исключение MalformedURLException . И оно может быть выброшено в случае, цитирую:
if no protocol is specified, or an unknown protocol is found, or spec is null, or the parsed URL fails to comply with the specific syntax of the associated protocol.

  1. Если протокол не указан.
  2. Найден неизвестный протокол.
  3. Спецификация имеет значение null .
  4. URL-адрес не соответствует конкретному синтаксису связанного протокола.

Давай создадим метод, который будет создавать объект класса URL :

Как только ты напишешь эти строки в IDE (я пишу в IDEA, но даже в Eclipse и NetBeans это сработает), увидишь вот это:

Это говорит о том, что нам надо либо пробросить исключение, либо “обернуть” в try-catch . Предлагаю пока выбрать второй вариант, чтобы наглядно увидеть, что получится:

 public static URL createURL() < URL url = null; try < url = new URL("https://javarush.com"); >catch(MalformedURLException e) < e.printStackTrace(); >return url; > 

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

Мы можем создать такое исключение, расширив RuntimeException в Java.

Непроверяемые исключения наследуются от класса Error или класса RuntimeException . Многие программисты считают, что мы не можем обрабатывать эти исключения в наших программах, потому что они представляют собой тип ошибок, от которых нельзя ожидать восстановления выполнения кода во время работы программы.

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

 public class OurCoolUncheckedException extends RuntimeException < public OurCoolUncheckedException(String message) < super(message); >public OurCoolUncheckedException(Throwable cause) < super(cause); >public OurCoolUncheckedException(String message, Throwable throwable) < super(message, throwable); >> 

Обрати внимание: мы сделали несколько конструкторов для разных целей. Это позволяет нам расширить возможности нашего исключения. Вот, к примеру, мы можем сделать так, чтобы исключение могло выдать нам код ошибки. Для начала сформируем enum , в котором, собственно, наши коды ошибок и будут лежать:

 public enum ErrorCodes < FIRST_ERROR(1), SECOND_ERROR(2), THIRD_ERROR(3); private int code; ErrorCodes(int code) < this.code = code; >public int getCode() < return code; >> 

А теперь добавим еще один конструктор в класс нашего исключения:

 public OurCoolUncheckedException(String message, Throwable cause, ErrorCodes errorCode)

И да, не забудем добавить поле, чуть было не забыли:

 private Integer errorCode; 

Ну и конечно, метод для получения этого кода:

 public Integer getErrorCode()

Посмотрим на весь класс целиком, чтобы можно было проверить и сравнить:

public class OurCoolUncheckedException extends RuntimeException < private Integer errorCode; public OurCoolUncheckedException(String message) < super(message); >public OurCoolUncheckedException(Throwable cause) < super(cause); >public OurCoolUncheckedException(String message, Throwable throwable) < super(message, throwable); >public OurCoolUncheckedException(String message, Throwable cause, ErrorCodes errorCode) < super(message, cause); this.errorCode = errorCode.getCode(); >public Integer getErrorCode() < return errorCode; >> 

Вот наше исключение и готово! Как видишь, ничего особо сложного нет. Проверим его в работе:

 public static void main(String[] args) < getException(); >public static void getException()

Запустим наше небольшое приложение и увидим в консоли примерно следующее:

А теперь давай воспользуемся дополнительной функциональностью, которую мы добавили. Немного допишем предыдущий код:

 public static void main(String[] args) throws Exception < OurCoolUncheckedException exception = getException(3); System.out.println("getException().getErrorCode() = " + exception.getErrorCode()); throw exception; >public static OurCoolUncheckedException getException(int errorCode)< return switch (errorCode) < case 1: return new OurCoolUncheckedException("Наше крутое исключение! Мы получили ошибку: " + ErrorCodes.FIRST_ERROR.getCode(), new Throwable(), ErrorCodes.FIRST_ERROR); case 2: return new OurCoolUncheckedException("Наше крутое исключение! Мы получили ошибку: " + ErrorCodes.SECOND_ERROR.getCode(), new Throwable(), ErrorCodes.SECOND_ERROR); default: // здесь мы подхватим тройку и все остальные коды, которые мы еще не добавили, то есть, это действие по умолчанию. Подробнее можешь узнать здесь Switch case Java (оператор switch в Java) (javarush.ru) return new OurCoolUncheckedException("Наше крутое исключение! Мы получили ошибку: " + ErrorCodes.THIRD_ERROR.getCode(), new Throwable(), ErrorCodes.THIRD_ERROR); > > 

С исключениями можно работать как с объектами, хотя, уверен, ты и так знаешь, что в Java все есть объект.

И смотри, что мы сделали. Сначала мы изменили метод, который теперь не бросает, а просто создает исключение в зависимости от того, какой нам прилетел параметр. Далее при помощи switch-case генерируем исключение с нужным нам кодом ошибки и сообщением. А в основном методе мы созданное исключение получили, достали код ошибки и бросили его.

Давай запустим и посмотрим, что попадет в консоль:

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

Ну как? Надеюсь, у тебя все получилось!

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

Очень хорошо про исключения в целом написал Брюс Эккель в своей книге “Философия Java”, в главе 12, рекомендую ознакомиться! Также загляни в первый том “Java. Библиотека профессионала” Хорстманна, в главу 7 — там тоже много интересного.

Небольшие итоги

  1. Пиши все в лог! Логируй сообщения, которые может выдать исключение. В большинстве случаев это очень поможет в отладке и позволит понять, что произошло. Не оставляй пустым блок catch , иначе он будет просто “съедать” исключение, и у тебя не будет данных для поиска проблем.

Источник

Пример создания исключения java

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

Чтобы создать свой класс исключений, надо унаследовать его от класса Exception. Например, у нас есть класс, вычисляющий факториал, и нам надо выбрасывать специальное исключение, если число, передаваемое в метод, меньше 1:

class Factorial < public static int getFactorial(int num) throws FactorialException< int result=1; if(num<1) throw new FactorialException("The number is less than 1", num); for(int i=1; i<=num;i++)< result*=i; >return result; > > class FactorialException extends Exception < private int number; public int getNumber()public FactorialException(String message, int num) < super(message); number=num; >>

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

Для генерации исключения в методе вычисления факториала выбрасывается исключение с помощью оператора throw: throw new FactorialException(«Число не может быть меньше 1», num) . Кроме того, так как это исключение не обрабатывается с помощью try..catch, то мы передаем обработку вызывающему методу, используя оператор throws: public static int getFactorial(int num) throws FactorialException

Теперь используем класс в методе main:

public static void main(String[] args) < try< int result = Factorial.getFactorial(6); System.out.println(result); >catch(FactorialException ex) < System.out.println(ex.getMessage()); System.out.println(ex.getNumber()); >>

Источник

Пример создания исключения java

правильно ли понимаю, что когда я работаю с проектом, в котором есть несколько потоков исполнения, может быть вот такая ситуация. Один из этих потоков запускается и завершается успешно, а затем выбрасывает исключение внутри блока try-catch. Оставшиеся потоки исполнения продолжают свою работу, но никакой код в блоке finally не выполняется. Тогда блок finally при обработке исключений не будет выполнен?

я читаю про исключения на 1м и в принципе понимаю, но не очень. ps: зачем только я начал с java core. pss: если вы это читаете, и я до сих пор на первом, то либо я прохожу другой курс, либо читаю книгу по джаве, параллельно проходя этот курс, либо решил взять перерыв на неопределенный срок времени. никогда не сдамся)

Есть подозрение, что так будет правильнее.

обращу внимание на некоторую неточность. цитата «Создание исключения При исполнении программы исключение генерируется JVM или вручную, с помощью оператора throw» в java исключения это тоже объекты поэтому создается исключение так же как объект new Exception. а бросается в программе с помощью оператора throw. обычно эти операции объединяют в одну throw new Exception(«aaa»);

если что я пишу это с 3 уровня. Под конец лекций я читал статью про бафридер, после нашел там ссылку на потоки вводов, а потом чтобы понять что там говориться ввел гугл про исключение и нашел эту статью, спасибо автору, это статья очень помогла. PS если ты читаешь этот комментарий и видишь что у меня нет прогресса(то есть если я все еще на 3 уровне или чуточку больше), то скажи мне, что я нуб и не дошел до 40 лвла

Источник

Оцените статью