Сведения о вопросе

Fhohir

23:05, 22nd August, 2020

Теги

Когда выбрать проверенные и непроверенные исключения

Просмотров: 420   Ответов: 18

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

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



  Сведения об ответе

9090

18:18, 1st August, 2020

Проверенные исключения хороши, если вы понимаете, когда их следует использовать. Ядро Java API не может следовать этим правилам для SQLException (а иногда и для IOException), поэтому они так ужасны.

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

Непроверенные исключения должны использоваться для всего остального.

Я расскажу вам об этом, потому что большинство людей не понимают, что это значит.

  1. Предсказуемо, но неосуществимо : вызывающий абонент сделал все, что было в его силах, чтобы проверить входные параметры, но какое-то условие вне его контроля привело к сбою операции. Например, вы пытаетесь прочитать файл, но кто-то удаляет его между временем проверки его существования и началом операции чтения. Объявляя проверенное исключение, вы говорите вызывающему абоненту, чтобы он предвидел этот сбой.
  2. Разумно восстанавливаться: нет смысла говорить вызывающим абонентам, чтобы они ожидали исключения, от которых они не могут восстановиться. Если пользователь пытается читать из несуществующего файла, вызывающий может запросить у него новое имя файла. С другой стороны, если метод терпит неудачу из-за ошибки программирования (недопустимые аргументы метода или ошибочная реализация метода), приложение ничего не может сделать, чтобы исправить проблему в середине выполнения. Лучшее, что он может сделать, это зарегистрировать проблему и подождать, пока разработчик исправит ее позже.

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

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

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


  Сведения об ответе

SKY

03:24, 29th August, 2020

От Java Обучаемость :

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

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

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


  Сведения об ответе

LIZA

21:21, 4th August, 2020

Правило, которое я использую: никогда не используйте непроверенные исключения! (или когда вы не видите никакого способа обойти это)

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


  Сведения об ответе

PHPH

10:33, 27th August, 2020

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

С проверенными исключениями ваше состояние обработки ошибок является микроуправляемым и невыносимым в любой большой системе.

Большую часть времени вы не знаете, является ли ошибка "recoverable", потому что вы не знаете, в каком слое находится вызывающий объект вашего API.

Предположим, что я создаю StringToInt API, который преобразует строковое представление целого числа в Int. Должен ли я бросить проверенное исключение, если API вызывается со строкой "foo" ? Можно ли его восстановить ? Я не знаю, потому что в его слое вызывающий объект my StringToInt API, возможно, уже проверил входные данные, и если это исключение выбрасывается, то это либо ошибка, либо повреждение данных, и оно не может быть восстановлено для этого слоя.

В этом случае вызывающий объект API не хочет перехватывать исключение. Он только хочет допустить исключение "bubble up". Если я выбрал проверенное исключение, у этого вызывающего будет много бесполезных блоков catch только для того, чтобы искусственно перестроить исключение.

То, что можно восстановить, большую часть времени зависит от вызывающего объекта API, а не от пишущего объекта API. An API не следует использовать проверенные исключения, так как только непроверенные исключения позволяют выбрать либо перехват, либо игнорирование исключения.


  Сведения об ответе

PHPH

13:47, 27th August, 2020

Вы совершенно правы.

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

Например:

/**
 * @params operation - The operation to execute.
 * @throws IllegalArgumentException if the operation is "exit"
 */
 public final void execute( String operation ) {
     if( "exit".equals(operation)){
          throw new IllegalArgumentException("I told you not to...");
     }
     this.operation = operation; 
     .....  
 }
 private void secretCode(){
      // we perform the operation.
      // at this point the opreation was validated already.
      // so we don't worry that operation is "exit"
      .....  
 }

Просто чтобы привести пример. Дело в том, что если система быстро выходит из строя, то вы будете знать, где и почему она потерпела неудачу. Вы получите stacktrace, как:

 IllegalArgumentException: I told you not to use "exit" 
 at some.package.AClass.execute(Aclass.java:5)
 at otherPackage.Otherlass.delegateTheWork(OtherClass.java:4569)
 ar ......

И ты узнаешь, что случилось. OtherClass в методе "delegateTheWork" (в строке 4569 ) вызывается ваш класс со значением "exit", даже если это не должно быть и т.д.

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

То же самое происходит и с NullPointerExceptions. Если у вас есть класс 700 строк с примерно 15 методами, который использует 30 атрибутов и ни один из них не может быть null, вместо проверки в каждом из этих методов на допустимость null вы можете сделать все эти атрибуты доступными только для чтения и проверить их в конструкторе или фабричном методе.

 public static MyClass createInstane( Object data1, Object data2 /* etc */ ){ 
      if( data1 == null ){ throw NullPointerException( "data1 cannot be null"); }

  }


  // the rest of the methods don't validate data1 anymore.
  public void method1(){ // don't worry, nothing is null 
      ....
  }
  public void method2(){ // don't worry, nothing is null 
      ....
  }
  public void method3(){ // don't worry, nothing is null 
      ....
  }

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

В этом случае вы или ваши коллеги ничего не можете сделать, чтобы помочь ему. Но все же вы должны что-то сделать и не дать приложению просто умереть и исчезнуть в глазах пользователя. Вы используете проверенное исключение для этого и обрабатываете исключение, что вы можете сделать, когда это произойдет?, большую часть времени, просто чтобы попытаться зарегистрировать ошибку, вероятно, сохраните свою работу ( работу приложения ) и представьте сообщение пользователю. ( Сайт blabla не работает, пожалуйста, повторите попытку позже и т. д. )

Если проверенное исключение используется чрезмерно ( путем добавления "throw Exception" в сигнатуры всех методов), то ваш код станет очень хрупким, потому что все будут игнорировать это исключение (потому что оно слишком общее), и качество кода будет серьезно скомпрометировано.

Если вы злоупотребляете непроверенным исключением, то произойдет нечто подобное. Пользователи этого кода не знают, если что-то может пойти не так, появится много try{...}catch( Throwable t).


  Сведения об ответе

lourence

06:40, 9th August, 2020

Вот мое "последнее эмпирическое правило".
Я использую:

  • непроверенное исключение в коде моего метода для сбоя из-за вызывающего объекта (что включает явную и полную документацию )
  • проверено исключение для сбоя из-за вызываемого абонента


  Сведения об ответе

darknet

02:09, 7th August, 2020

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

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

Это философия, используемая многими фреймворками. Spring и hibernate, в частности, приходят на ум - они преобразуют известное проверенное исключение в непроверенное исключение именно потому, что проверенные исключения чрезмерно используются в Java. Один пример, который я могу вспомнить, это JSONException из json.org, который является проверенным исключением и в основном раздражает - он должен быть непроверенным,но разработчик просто не продумал его.

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


  Сведения об ответе

baggs

11:29, 22nd August, 2020

Вот очень простое решение вашей проверенной/непроверенной дилеммы.

Правило 1: считайте непроверенное исключение тестируемым условием перед выполнением кода. например…

x.doSomething(); // the code throws a NullPointerException

где x - это null... ...код, возможно, должен иметь следующее…

if (x==null)
{
    //do something below to make sure when x.doSomething() is executed, it won’t throw a NullPointerException.
    x = new X();
}
x.doSomething();

Правило 2: считайте проверяемое исключение непроверяемым условием, которое может возникнуть во время выполнения кода.

Socket s = new Socket(“google.com”, 80);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();

...в приведенном выше примере URL (google.com) может быть недоступен из-за того, что сервер DNS не работает. Даже в тот момент, когда сервер DNS работал и разрешил имя ' google.com ' на адрес IP, если соединение будет сделано с google.com, в любое время послесловие, сеть может выйти из строя. Вы просто не можете тестировать сеть все время перед чтением и записью в потоки.

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

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

В этом есть серая зона. В случае, если требуется много тестов (умопомрачительный оператор if с большим количеством && и||), исключение будет выдано CheckedException просто потому, что это слишком большая боль, чтобы получить правильный ответ — вы просто не можете сказать, что эта проблема является ошибкой программирования. Если существует гораздо меньше 10 тестов (например 'if (x == null)’), то ошибка программиста должна быть UncheckedException.

Все становится интересным, когда имеешь дело с языковыми переводчиками. Согласно приведенным выше правилам, следует ли считать синтаксическую ошибку проверенным или непроверенным исключением? Я бы сказал, что если синтаксис языка можно проверить до его выполнения, то он должен быть UncheckedException. Если язык не может быть протестирован-подобно тому, как код assembly выполняется на персональном компьютере, то синтаксическая ошибка должна быть проверенным исключением.

2 правила выше, вероятно, снимут 90% вашей заботы о том, из чего выбирать. Чтобы обобщить правила, следуйте этой схеме… 1) если код, подлежащий исполнению, может быть протестирован до его выполнения, чтобы он работал правильно, и если возникает исключение — a.k.a. ошибка программиста, исключение должно быть UncheckedException (подкласс RuntimeException). 2) если код, который должен быть выполнен, не может быть протестирован до его выполнения, чтобы он работал правильно, исключение должно быть проверенным исключением (подкласс исключения).


  Сведения об ответе

COOL

19:10, 20th August, 2020

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


  Сведения об ответе

COOL

23:27, 11th August, 2020

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

Непроверенное исключение: если клиент не может ничего сделать после исключения, то вызовите непроверенное исключение.

Пример: если предполагается выполнить арифметическую операцию в методе A() и на основе выходных данных из A(), необходимо выполнить другую операцию. Если выходные данные являются null из метода A(), который вы не ожидаете во время выполнения, то вы должны бросить Null исключение указателя, которое является исключением времени выполнения.

Смотрите здесь


  Сведения об ответе

VCe znayu

18:44, 6th August, 2020

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

Я нахожу проверенные исключения полезными на более низком уровне, как деталь реализации. Это часто кажется лучшим механизмом управления потоком, чем необходимость управлять заданной ошибкой "return code". Иногда это может помочь увидеть влияние идеи для изменения кода низкого уровня тоже... объявите проверенное исключение ниже по потоку и посмотрите, кто будет нуждаться в корректировке. Этот последний пункт не применяется, если есть много общих: catch (исключение e) или throws Exception , которые обычно не слишком хорошо продуманы в любом случае.


  Сведения об ответе

VERSUION

17:28, 29th August, 2020

Вот я и хочу поделиться своим мнением у меня после многих лет развития есть опыт:

  1. Отмеченное исключение. Это часть бизнес-прецедента или потока вызовов, это часть логики приложения, которую мы ожидаем или не ожидаем. Например, соединение отклонено, условие не выполнено и т. д. Нам нужно обработать его и показать соответствующее сообщение пользователю с инструкциями, что произошло и что делать дальше (повторите попытку позже и т. д.). Я обычно называю это исключение постобработки или исключение "user".

  2. Непроверенное исключение. Это часть исключения программирования, некоторая ошибка в программировании программного кода (ошибка, дефект) и отражает способ, как программисты должны использовать API в соответствии с документацией. Если внешний lib / framework doc говорит, что он ожидает получить данные в некотором диапазоне и не null, потому что NPE или IllegalArgumentException будут брошены, программист должен ожидать этого и использовать API правильно в соответствии с документацией. В противном случае будет выдано исключение. Я обычно называю это исключением предварительной обработки или исключением "validation".

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

  1. Отмеченное исключение. Целевая аудитория-users/clients.
  2. Непроверенное исключение. Целевая аудитория-разработчики. Другими словами, непроверенные исключения предназначены только для разработчиков.

По фазе жизненного цикла разработки приложений.

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

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


  Сведения об ответе

lats

18:39, 8th August, 2020

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

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


  Сведения об ответе

FAriza

05:57, 28th August, 2020

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

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

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

Исключение времени выполнения используется, когда исключение, скорее всего, произошло, нет никакого способа идти дальше и ничего не может быть восстановлено. Поэтому в данном случае мы можем принять меры предосторожности в отношении этого исключения. EX: NUllPointerException, ArrayOutofBoundsException. Это с большей вероятностью произойдет. В этом случае мы можем принять меры предосторожности при кодировании, чтобы избежать такого исключения. В противном случае нам придется писать блоки try catch везде.

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


  Сведения об ответе

JUST___

07:40, 23rd August, 2020

Я думаю, что мы можем думать об исключениях из нескольких вопросов:

почему изъятие происходит? Что мы можем сделать, когда это произойдет

по ошибке-жучок. например, вызывается метод объекта null.

String name = null;
... // some logics
System.out.print(name.length()); // name is still null here

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

при вводе извне вы не можете контролировать или доверять выводу внешней службы.

String name = ExternalService.getName(); // return null
System.out.print(name.length());    // name is null here

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

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

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

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

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

В этом случае нужно ли нам знать, какое исключение произошло в ExternalService? Это зависит:

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

  2. если вам нужен журнал или ответ для пользователя конкретного execption, вы можете поймать их. Для других-мыльный пузырь.


  Сведения об ответе

+-*/

05:12, 1st August, 2020

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

  • Если ошибка является ошибкой программиста, то это должно быть непроверенное исключение .


  Сведения об ответе

davran

23:14, 7th August, 2020

Я думаю, что при объявлении исключения приложения это должно быть непроверенное исключение, т. е. подкласс RuntimeException. Причина в том, что он не будет загромождать код приложения с помощью try-catch и бросает объявление на метод. Если ваше приложение использует Java Api, которое выдает проверенные исключения, которые в любом случае должны быть обработаны. В других случаях приложение может выдать непроверенное исключение. Если вызывающему приложению все еще нужно обработать непроверенное исключение, это можно сделать.


  Сведения об ответе

dumai

02:43, 8th August, 2020

Правило, которое я использую: никогда не используйте непроверенные исключения! (или когда вы не видите никакого способа обойти это)

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

Таким образом, конечный пользователь все еще может быть представлен с сообщением об ошибке, вместо того, чтобы приложение полностью исчезло.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться