Коли вибирати перевірені та неперевірені винятки


213

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

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


11
Баррі Рузек написав чудовий посібник щодо вибору перевірених чи неперевірених винятків.
sigget

Відповіді:


241

Перевірені винятки чудові, якщо ви розумієте, коли їх потрібно використовувати. API ядра Java не дотримується цих правил для SQLException (а іноді і для IOException), тому вони такі жахливі.

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

Необхідні неперевірені винятки слід використовувати для всього іншого.

Я зламаю це для вас, бо більшість людей неправильно розуміють, що це означає.

  1. Передбачувана, але непередбачувана : Абонент зробив усе, що було в їх силах, для підтвердження вхідних параметрів, але деяка умова, що знаходиться поза їх контролем, призвела до збою операції. Наприклад, ви намагаєтеся прочитати файл, але хтось видаляє його між часом, коли ви перевіряєте, чи існує він, і часом початку операції читання. Заявивши перевірений виняток, ви повідомляєте абоненту передбачити цю помилку.
  2. Розумно відновлюватись : Немає сенсу спонукати абонентів передбачати винятки, з яких вони не можуть відновитись. Якщо користувач намагається прочитати з неіснуючого файлу, абонент може запропонувати їм нове ім'я файлу. З іншого боку, якщо метод виходить з ладу через помилку програмування (недійсні аргументи методу або реалізацію баггі-методу), програма нічого не може зробити для усунення проблеми в середині виконання. Найкраще це зробити - зареєструвати проблему та дочекатися, коли розробник виправить її пізніше.

Якщо виняток, який ви кидаєте, не відповідає всім перерахованим вище умовам, він повинен використовувати Неперевірене виняток.

Переоцінюйте на кожному рівні : Іноді метод лову перевіреного винятку не є правильним місцем для вирішення помилки. У такому випадку подумайте, що розумно для власних абонентів. Якщо виняток передбачуваний, непередбачуваний та обґрунтований для відновлення після цього, ви повинні кинути перевірений виняток самостійно. Якщо ні, то ви повинні перетворити виняток у неперевірений виняток. Якщо ви будете дотримуватися цього правила, ви зможете перетворити перевірені винятки в неперевірені винятки і навпаки, залежно від того, на якому шарі ви перебуваєте.

Як перевірені, так і неперевірені винятки, використовуйте правильний рівень абстракції . Наприклад, сховище коду з двома різними реалізаціями (база даних та файлова система) повинно уникати викриття специфічних для реалізації деталей шляхом перекидання SQLExceptionабо IOException. Натомість він повинен містити виняток у абстракції, що охоплює всі реалізації (наприклад RepositoryException).


2
"ви намагаєтеся прочитати файл, але хтось видаляє його між часом, коли ви перевіряєте, чи він існує, і часом, коли починається операція читання." => Як це навіть "очікується"? Для мене це звучить більше як: Несподіване та запобіжне. Хто очікує, що файл буде видалений лише між двома заявами?
Корай Тугай

9
@KorayTugay Очікуване не означає, що сценарій є типовим. Це просто означає, що ми можемо передбачити, що ця помилка відбудеться достроково (порівняно з помилками програмування, яких неможливо передбачити достроково). Непередбачуваний стосується того, що програміст нічого не може зробити для того, щоб користувач чи інші додатки не могли видалити файл між часом, який ми перевіряємо, чи існує він, і часом початку операції читання.
Гілі

Отже, будь-які проблеми, пов’язані з базою даних, у межах методу повинні кидати перевірене виключення?
ivanjermakov

59

Від учня Java :

Коли виняток виникає, вам потрібно або виловити і обробити виняток, або сказати компілятору, що ви не можете впоратися з ним, оголосивши, що ваш метод скидає цей виняток, тоді код, який використовує ваш метод, повинен буде обробляти цей виняток (навіть він Також може вирішити заявити, що він кидає виняток, якщо він не може впоратися з цим).

Компілятор перевірить, що ми зробили одну з двох речей (зловити або оголосити). Тому їх називають перевіреними винятками. Але помилки та винятки під час виконання не перевіряються компілятором (навіть якщо ви можете вибрати, щоб зловити або оголосити, це не потрібно). Отже, ці два називаються Неперевіреними винятками.

Помилки використовуються для представлення тих умов, які виникають поза додатком, таких як збій системи. Винятки з виконання, як правило, трапляються з помилки в логіці програми. У цих ситуаціях ви нічого не можете зробити. Коли трапляються винятки з виконання, вам доведеться переписати код програми. Отже, вони не перевіряються компілятором. Ці винятки з виконання будуть виявлятися в процесі розробки та тестування. Тоді нам доведеться перефактурувати наш код, щоб усунути ці помилки.


13
Це православний погляд. Але тут багато суперечок.
artbristol

49

Я використовую правило: ніколи не використовуйте неперевірені винятки! (або коли ви нічого не бачите)

Існує дуже вагомий випадок протилежного: Ніколи не використовуйте перевірені винятки. Я не хочу брати участь у дискусії, але, мабуть, існує широкий консенсус, що введення перевірених винятків було неправильним заднім числом. Будь ласка, не знімайте месенджера та посилайтеся на ці аргументи .


3
IMHO, перевірені винятки могли бути головним активом, якби був простий спосіб, щоб метод заявив, що не очікує, що методи, викликані в певному блоці коду, викидають певні винятки (або взагалі будь-які), і що будь-який перевірений винятки, які викидаються всупереч такому очікуванню, повинні бути зафіксовані в іншому типі винятків та повторно скинуті. Я вважаю, що 90% часу, коли код не готовий впоратись із перевіреним винятком, таке перемотування та повторне перекидання було б найкращим способом впоратися з цим, але оскільки немає мовної підтримки, це рідко робиться.
supercat

@supercat По суті, це все: я шалений фанат суворої перевірки типу і перевірені винятки є логічним розширенням цього. Я повністю відмовився від перевірених винятків, хоча концептуально їм дуже подобаються.
Конрад Рудольф

1
Один peeve, який я маю з дизайном винятків, який би вирішив описаний нами механізм, - це те, що якщо fooце задокументовано як кидання barExceptionпід час читання минулого кінця файлу, і fooвикликає метод, який кидає, barExceptionнавіть fooне чекаючи цього, код, який викликає foo, вважатиме, що кінець файлу досягнуто, і не матиме поняття, що сталося щось несподіване. Я вважаю, що ця ситуація є тією, де перевірені винятки мають бути найбільш корисними, але це також єдиний випадок, коли компілятор дозволить не обробляти перевірені винятки.
supercat

@supercat: У коді вже є простий спосіб зробити те, що ви хочете, у першому коментарі: загортайте код у блок спробу, вловлюйте виняток і загортайте виняток у програму RuntimeException та повторне скидання.
Warren Dew

1
@KonradRudolph supercat посилався на "певний блок коду"; Враховуючи, що блок повинен бути визначений, декларативний синтаксис не суттєво зменшить потужність. Якщо ви думаєте, що це було б декларативно для всієї функції, це сприяло б поганому програмуванню, оскільки люди просто дотримуватимуться декларації замість того, щоб насправді дивитись на перевірені виключення, які потенційно потрапляють, і переконайтесь, що немає іншого кращого способу обробляти їх.
Warren Dew

46

У будь-якій достатньо великій системі, що має багато шарів, перевірене виключення є марними, оскільки, в будь-якому випадку, вам потрібна стратегія архітектурного рівня для управління способом обробки винятку (використовуйте бар'єр помилок)

За вивіреними винятками, ваша система керування помилками керується мікроконтролем і нестерпна для будь-якої великої системи.

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

Скажімо, я створюю StringToInt API, який перетворює рядкове представлення цілого числа в Int. Чи повинен я кинути перевірений виняток, якщо API викликається рядком "foo"? Це підлягає відшкодуванню? Я не знаю, тому що в його шарі абонент мого API StringToInt, можливо, вже підтвердив вхідні дані, і якщо цей виняток буде викинутий, це або помилка, або пошкодження даних, і він не підлягає відновленню для цього шару.

У цьому випадку абонент API не хоче перехопити виняток. Він лише хоче, щоб виняток "пузирився". Якщо я вибрав перевірений виняток, у цього абонента буде достатньо непотрібного блоку вилову лише для штучного повторного скидання винятку.

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


3
Це дуже близько до userstories.blogspot.com/2008/12/…
alexsmail

16
@alexsmail Інтернет ніколи не здивує мене, насправді це мій блог :)
Стефан

30

Ви маєте рацію.

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

Наприклад:

/**
 * @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"
      .....  
 }

Просто на приклад. Справа в тому, що якщо система швидко виходить з ладу, то ви будете знати, де і чому вона вийшла з ладу. Ви отримаєте стек-трек на зразок:

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

І ти будеш знати, що сталося. Інший клас в методі "delegateTheWork" (у рядку 4569) назвав ваш клас значенням "вихід", навіть коли він не повинен і т.д.

В іншому випадку вам доведеться розпорошувати валідації по всьому коду, і це схильне до помилок. Крім того, іноді важко відстежити, що пішло не так, і ви можете очікувати годин розчарування налагодження

Те саме відбувається і з NullPointerExceptions. Якщо у вас є клас 700 рядків з 15 методами, який використовує 30 атрибутів, і жоден з них не може бути нульовим, замість перевірки в кожному з цих методів для зведення нанівець ви можете зробити всі ці атрибути лише для читання та перевірити їх у конструкторі чи заводський метод.

 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 
      ....
  }

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

У цьому сценарії немає нічого, що ви або ваші колеги можете зробити, щоб допомогти йому. Але все-таки потрібно щось робити і не дозволяти додатку просто вмирати і зникати в очах користувача. Ви використовуєте для цього перевірений виняток і обробляєте виняток, що ви можете зробити, коли це трапиться? Здебільшого, просто для того, щоб спробувати зафіксувати помилку, ймовірно, збережіть свою роботу (робота в додатку) та подайте повідомлення користувачеві . (Блабла сайту відсутня. Повторіть спробу пізніше тощо)

Якщо перевірений виняток буде надмірно використаний (додавши «викинути виняток» у всі підписи методів), то ваш код стане дуже крихким, тому що всі ігнорують цей виняток (бо занадто загальний) і якість коду буде серйозно скомпрометований.

Якщо ви будете зловживати неперевіреним винятком, трапиться щось подібне. Користувачі цього коду не знають, чи може щось піти не так, з’явиться багато спроб {...} catch (Throwable t).


2
Добре сказано! +1. Мене завжди дивує, що ця відмінність абонента (неперевірений) / виклику (перевірено) не є більш очевидним ...
VonC

19

Ось моє «остаточне правило».
Я використовую:

  • неперевірений виняток у коді мого методу за збій через абонента (що включає явну та повну документацію )
  • перевірено виняток на помилку через виклику, який мені потрібно зробити явним для всіх, хто хоче використовувати мій код

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


Для обох цих винятків я створити власний неперевірений і перевірений виняток для мого додатка (хороша практика, як згадувалося тут ), за винятком дуже поширеного неперевіреного винятку (наприклад, NullPointerException)

Так, наприклад, ціль цієї конкретної функції нижче - зробити (або отримати, якщо він вже існує) об'єктом,
тобто:

  • контейнер об'єкта, який потрібно зробити / отримати, ОБОВ'ЯЗКОВО існувати (відповідальність CALLER
    => неперевірений виняток, і ясний коментар javadoc для цієї викликаної функції)
  • інші параметри не можуть бути нульовими
    (вибір кодера, який слід поставити на CALLER: кодер не перевірятиме параметр null, але кодер робить ДОКУМЕНТ)
  • результат НЕ МОЖЕ бути НУЛЬНИМ
    (відповідальність та вибір коду абонента, вибір якого буде представляти великий інтерес для абонента
    => перевірений виняток, оскільки кожен абонент ОБОВ'ЯЗКОВО приймати рішення, якщо об'єкт неможливо створити / знайти, і що рішення має бути виконане під час компіляції: вони не можуть використовувати цю функцію, не маючи справу з цією можливістю, тобто з цим перевіреним винятком).

Приклад:


/**
 * Build a folder. <br />
 * Folder located under a Parent Folder (either RootFolder or an existing Folder)
 * @param aFolderName name of folder
 * @param aPVob project vob containing folder (MUST NOT BE NULL)
 * @param aParent parent folder containing folder 
 *        (MUST NOT BE NULL, MUST BE IN THE SAME PVOB than aPvob)
 * @param aComment comment for folder (MUST NOT BE NULL)
 * @return a new folder or an existing one
 * @throws CCException if any problems occurs during folder creation
 * @throws AssertionFailedException if aParent is not in the same PVob
 * @throws NullPointerException if aPVob or aParent or aComment is null
 */
static public Folder makeOrGetFolder(final String aFoldername, final Folder aParent,
    final IPVob aPVob, final Comment aComment) throws CCException {
    Folder aFolderRes = null;
    if (aPVob.equals(aParent.getPVob() == false) { 
       // UNCHECKED EXCEPTION because the caller failed to live up
       // to the documented entry criteria for this function
       Assert.isLegal(false, "parent Folder must be in the same PVob than " + aPVob); }

    final String ctcmd = "mkfolder " + aComment.getCommentOption() + 
        " -in " + getPNameFromRepoObject(aParent) + " " + aPVob.getFullName(aFolderName);

    final Status st = getCleartool().executeCmd(ctcmd);

    if (st.status || StringUtils.strictContains(st.message,"already exists.")) {
        aFolderRes = Folder.getFolder(aFolderName, aPVob);
    }
    else {
        // CHECKED EXCEPTION because the callee failed to respect his contract
        throw new CCException.Error("Unable to make/get folder '" + aFolderName + "'");
    }
    return aFolderRes;
}

19

Це не лише питання здатності відновитися після винятку. Найважливіше, на мою думку, полягає в тому, зацікавлений абонент, щоб вилучити виняток чи ні.

Якщо ви пишете бібліотеку, яка буде використовуватися в іншому місці, або рівень нижчого рівня у вашій програмі, запитайте себе, чи є абонент зацікавлений у визначенні (знанні про) вашого винятку. Якщо його немає, то використовуйте неперевірений виняток, щоб ви не обтяжували його зайвим.

Це філософія, яка використовується багатьма рамками. Зокрема, весна і сплячка приходять до тями - вони перетворюють відомий перевірений виняток у неперевірений виняток саме тому, що перевірені винятки надмірно використовуються на Java. Один із прикладів, які я можу придумати, - це JSONException від json.org, який є перевіреним винятком і в основному дратує - це слід не перевірити, але розробник просто не продумав це.

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


13

Ось дуже просте рішення вашої дилеми "Перевірена / перевірена".

Правило 1: Подумайте про неперевірений виняток як пробну умову перед виконанням коду. наприклад…

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

де x дорівнює нулю ... ... код, можливо, повинен мати наступне ...

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, який винайшов цю концепцію.

Взагалі майже всі API на Java дотримуються 2 правил, наведених вище. Якщо ви спробуєте записати у файл, диск може заповнитись перед завершенням запису. Можливо, що інші процеси спричинили заповнення диска. Тестування на цю ситуацію просто немає. Для тих, хто взаємодіє з обладнанням, де в будь-який час використання апаратури може вийти з ладу, перевірені винятки здаються елегантним рішенням цієї проблеми.

До цього є сіра зона. У випадку, якщо потрібно багато тестів (думка, якщо висловлювання з великою кількістю && і ||), виняток буде вивіреним CheckedException просто тому, що це занадто багато болю, щоб виправитись - ви просто не можете сказати цю проблему - помилка програмування. Якщо є набагато менше 10 тестів (наприклад, 'if (x == null)'), помилка програміста повинна бути UncontException.

Речі стають цікавими при спілкуванні з перекладачами мови. Відповідно до вищезазначених правил, чи слід вважати помилку синтаксису винятком, що перевіряється чи не перевіряється? Я можу стверджувати, що якщо синтаксис мови можна перевірити до того, як він буде виконаний, це повинен бути UncontException. Якщо мова не може бути перевірена - подібно до того, як працює збірний код на персональному комп’ютері, то помилка синтаксису повинна бути перевіреною винятком.

2 вищевказані правила, ймовірно, знімуть 90% вашої турботи, щодо чого вибрати. Щоб узагальнити правила, дотримуйтесь цього шаблону ... 1) якщо код, який потрібно виконати, може бути протестований перед його виконанням для його правильного запуску, і якщо виняток виникає - він же помилка програміста, виняток повинен бути UncontException (підклас RuntimeException ). 2) якщо код, який потрібно виконати, не може бути перевірений перед його правильним виконанням для його правильного запуску, виняток повинен бути перевіреним винятком (підклас винятку).


9

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


1
+1 Зазначимо, що примірні тести можуть бути кращим способом вирішити проблему, яку перевіряють виключення.
Кіт Пінсон

+1 для тестування одиниць. Використання перевірених / Поставлених галочок виключень мало впливає на якість коду. Тож аргумент, що якщо використовувати перевірені винятки, це призведе до кращої якості коду - це повний хибний аргумент!
користувач1697575

7

Перевірена виняток: Якщо клієнт може відновити виняток і хотів би продовжити, використовуйте перевірений виняток.

Неперевірене виняток: якщо клієнт не може зробити нічого після винятку, то підніміть неперевірений виняток.

Приклад: Якщо очікується, що ви будете робити арифметичні операції методом A () та на основі виводу з A (), вам доведеться виконати іншу операцію. Якщо вихідний параметр є нульовим методом A (), якого ви не очікуєте під час виконання програми, то, як очікується, викинете Null pointer Exception, який є виключенням часу виконання.

Зверніться сюди


2

Я погоджуюся з перевагою неперевірених винятків, як правило, особливо при розробці API. Абонент може завжди вибрати спійманий документально вивірений виняток. Ви просто не зайве змушувати абонента.

Я вважаю перевірені винятки корисними на нижчому рівні, як деталі реалізації. Часто це здається кращим потоком механізму управління, ніж керувати заданою помилкою "код повернення". Іноді це може допомогти побачити вплив ідеї щодо зміни коду низького рівня ... оголосити перевірений виняток вниз за течією та побачити, кому потрібно скоригуватись. Останній пункт не застосовується, якщо є багато загальних: catch (виняток e) або кидає виняток, який, як правило, не надто продуманий.


2

Ось я хочу поділитися своєю думкою, яку маю після багаторічного досвіду розвитку:

  1. Перевірено виняток. Це частина випадку використання бізнесу або потоку викликів, це частина логіки програми, яку ми очікуємо або не очікуємо. Наприклад, з'єднання відхилено, умова не виконується і т. Д. Нам потрібно обробити його та показати користувачеві відповідне повідомлення з інструкціями, що сталося та що робити далі (спробуйте пізніше тощо). Зазвичай я називаю це виняток після обробки або виняток "user".

  2. Неперевірений виняток. Це частина виключення з програмування, якась помилка в програмуванні програмного коду (помилка, дефект) і відображає спосіб, яким програмісти повинні використовувати API відповідно до документації. Якщо зовнішній документ lib / frame каже, що він очікує отримання даних у деякому діапазоні та ненульовому, тому що NPE або IllegalArgumentException буде викинуто, програміст повинен очікувати цього та правильно використовувати API відповідно до документації. Інакше виняток буде кинутий. Зазвичай я називаю це виняток перед обробкою або виняток "валідація".

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

  1. Перевірено виняток. Цільова аудиторія - це користувачі / клієнти.
  2. Неперевірений виняток. Цільова аудиторія - це розробники. Іншими словами неперевірені винятки призначені лише для розробників.

За фазою життєвого циклу розробки додатків.

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

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


2

Ми повинні розрізняти ці два типи винятку на основі того, чи це помилка програміста чи ні.

  • Якщо помилка є помилкою програміста, вона повинна бути неперевіреною винятком . Наприклад: SQLException / IOException / NullPointerException. Ці винятки - це помилки програмування. З ними повинен працювати програміст. Хоча в API JDBC, SQLException перевіряється винятком, навесні JDBCTemplate - це неперевірене виняток. Програміст не турбується про SqlException при використанні Spring.
  • Якщо помилка - це не помилка програміста, а причина виходить із зовнішньої сторони, вона повинна бути перевіреною винятком. Наприклад: якщо файл видалено або дозвіл на файл змінив хтось інший, його слід відновити.

FileNotFoundException - хороший приклад для розуміння тонких відмінностей. FileNotFoundException кидається у випадку, якщо файл не знайдено. Існує дві причини цього винятку. Якщо шлях до файлу визначається розробником або береться від кінцевого користувача через графічний інтерфейс, це повинен бути неперевірений виняток. Якщо файл видалено кимось іншим, це повинен бути перевірений виняток.

Перевірена виняток може оброблятися двома способами. Вони використовують try-catch або поширюють виняток. У разі розповсюдження винятку всі методи в стеку викликів будуть щільно з'єднані через обробку винятків. Тому ми повинні обережно використовувати перевірені винятки.

Якщо ви розробляєте шарувату корпоративну систему, для викидання вибираєте здебільшого неперевірений виняток, але не забувайте використовувати перевірений виняток для випадку, коли ви нічого не можете зробити.


1

Перевірені винятки корисні для випадків, що підлягають відновленню, коли ви бажаєте надати інформацію абоненту (наприклад, недостатньо дозволів, файл не знайдений тощо).

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


Я не згоден з вашим твердженням: "Неперевірені винятки використовуються рідко, якщо взагалі", насправді це повинно бути навпаки! Використовуйте неперевірені виправлення за замовчуванням, коли розробляєте ієрархію винятків додатків. Дозвольте розробникам вирішувати, коли вони хочуть обробляти виняток (наприклад, вони не змушені ставити блоки вилову або ставити підкидання, якщо вони не знають, як з цим поправитись).
користувач1697575

1

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

Щоразу, коли ми хочемо зробити щось значуще, коли відбувається певний виняток, і коли цей виняток очікується, але не є певним, тоді ми можемо використовувати перевірені винятки.

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

Виняток під час виконання використовується, коли виняток, найімовірніше, трапився, немає можливості йти далі і нічого не підлягає відшкодуванню. Тож у цьому випадку ми можемо вжити запобіжних заходів щодо цього винятку. EX: NUllPointerException, ArrayOutofBoundsException. Такі випадки частіше трапляються. У цьому випадку ми можемо вжити заходів обережності під час кодування, щоб уникнути такого винятку. Інакше нам доведеться писати блоки спробувати catch.

Більш загальні винятки можна зробити без перевірки, менше загальних перевіряти.


1

Я думаю, що ми можемо подумати про експедицію з кількох питань:

чому відбувається звільнення? Що ми можемо зробити, коли це станеться

помилково, помилка. наприклад, називається метод нульового об'єкта.

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

Тут вам може знадобитися перевірити, чи ім'я є недійсним, якщо ви хочете продовжувати, коли воно є недійсним, інакше ви можете залишити його в спокої, і воно зупиниться тут і надасть виклику час виконання. Такого роду винятки не потрібно перевіряти.

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

Тут вам може знадобитися вилучити всі винятки з ExternalService, якщо ви хочете продовжити, коли це станеться, в іншому випадку ви можете відпустити його, і він зупиниться тут і надасть виклику час винятку.

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

Тут вам може знадобитися вилучити всі винятки з ExternalService, якщо ви хочете продовжити, коли це станеться, в іншому випадку ви можете відпустити його, і він зупиниться тут і надасть виклику час винятку.

У цьому випадку ми повинні знати, який виняток стався в ExternalService? Це залежить:

  1. якщо ви можете впоратись із деякими винятками, вам потрібно знайти їх та обробити. Для інших киньте їх.

  2. якщо вам потрібен журнал або відповідь на конкретне виконання користувача, ви можете їх зловити. Для інших киньте їх.


0

Я думаю, що при оголошенні винятку програми він повинен бути Неперевіреним винятком, тобто підкласом RuntimeException. Причина полягає в тому, що він не захаращує код програми із пробним входом і кидає декларацію про метод. Якщо у вашій програмі використовується Java Api, яка видаляє перевірені винятки, з якими все-таки потрібно обробити. Для інших випадків додаток може кидати неперевірений виняток. Якщо абонент додатка все ще потребує обробки неперевіреного винятку, це можна зробити.


-12

Я використовую правило: ніколи не використовуйте неперевірені винятки! (або коли ви нічого не бачите)

З точки зору розробника, який використовує вашу бібліотеку, або кінцевого користувача, який використовує вашу бібліотеку / додаток, він дійсно може бути протистояним програмі, яка виходить з ладу через невдалене виключення. І розраховувати на вилов - це теж не добре.

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


1
Ви не пояснюєте, що, на вашу думку, не так, у загальному випадку для більшості неперевірених винятків.
Метью Флашен

Повністю не згоден з вашою
необґрунтованою
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.