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


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

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

18 163

18 ответов:

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

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

Неотмеченные Исключения следует использовать для все остальное.

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

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

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

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

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

с Ученик Java:

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

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

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

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

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

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

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

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

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

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

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

вы правы.

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

например:

/**
 * @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 ) вызвал ваш класс со значением" exit", даже если он не должен и т. д.

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

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

 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" во все сигнатуры методов), то ваш код станет очень хрупким, потому что все будут игнорировать это исключение (потому что слишком общее ) и качество кода будет быть серьезно скомпрометирована.

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

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

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

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


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

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

  • контейнер объекта для создания / получения должен существовать (ответственность вызывающего
    = > непроверенное исключение и очистить комментарий javadoc для этой вызываемой функции)
  • другие параметры не могут быть null
    (выбор кодера, чтобы поставить это на вызывающего абонента: кодер не будет проверять наличие нулевого параметра, но кодер документирует его)
  • результат НЕ МОЖЕТ БЫТЬ 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;
}

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

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

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

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

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

Правило 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, который изобрел эту концепцию.

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

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

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

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

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

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

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

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

см. здесь

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

по ошибки, ошибки. например, вызывается метод нулевого объекта.

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? это зависит от:

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

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

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

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

  • если ошибка является ошибкой программиста, она должна быть непроверенным исключением. например: SQLException/IOException / NullPointerException. Эти исключения являются ошибка в программе. Они должны быть обработаны программистом. В то время как в В JDBC API, то ситуацию sqlexception-это проверенное исключение, в Spring JDBCTemplate это непроверенное исключение.Программист не переживай SqlException, когда используется Весна.
  • если ошибка не является ошибкой программиста и причина исходит от внешнего, это должно быть проверенное исключение. например: если файл удаляется или разрешение файла изменяется кем-то другим, это должны быть восстановлены.

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

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

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

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

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

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