Java: проверено против непроверенного объяснения исключений
Я прочитал несколько сообщений на StackOverFlow о проверенных и непроверенных исключений. Я, честно говоря, до сих пор не совсем уверен, как правильно их использовать.
Джошуа Блох в " Эффективной Яве " сказал, что
Используйте проверенные исключения для восстанавливаемых условий и исключения времени выполнения для ошибок программирования (элемент 58 во 2-й редакции)
Посмотрим, правильно ли я это понимаю.
Вот мое понимание проверенного исключения:
try{
String userInput = //read in user input
Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
id = 0; //recover the situation by setting the id to 0
}
1. Вышеуказанное рассматривает проверенное исключение?
2. Является ли RuntimeException непроверенным исключением?
Вот мое понимание непроверенного исключения:
try{
File file = new File("my/file/path");
FileInputStream fis = new FileInputStream(file);
}catch(FileNotFoundException e){
//3. What should I do here?
//Should I "throw new FileNotFoundException("File not found");"?
//Should I log?
//Or should I System.exit(0);?
}
4. Разве вышеприведенный код не может быть проверенным исключением? Я могу попытаться восстановить ситуацию, как это? Могу я? (Примечание: мой третий вопрос находится внутри catch
выше)
try{
String filePath = //read in from user input file path
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
}catch(FileNotFoundException e){
//Kindly prompt the user an error message
//Somehow ask the user to re-enter the file path.
}
5. Почему люди делают это?
public void someMethod throws Exception{
}
Почему они позволяют всплыть исключение? Разве обработка ошибок не быстрее, лучше? Зачем пузыриться?
РЕДАКТИРОВАТЬ: я должен всплыть точное исключение или замаскировать его с помощью исключения?
Ниже мои чтения
21 ответ
Многие люди говорят, что проверенные исключения (то есть те, которые вы должны явно перехватить или перебросить) не должны использоваться вообще. Например, они были исключены в C#, и большинство языков не имеют их. Таким образом, вы всегда можете бросить подкласс RuntimeException
(непроверенное исключение)
Тем не менее, я думаю, что проверенные исключения полезны - они используются, когда вы хотите заставить пользователя вашего API подумать, как справиться с исключительной ситуацией (если она может быть исправлена). Просто проверенные исключения чрезмерно используются в платформе Java, что заставляет людей ненавидеть их.
Вот мой расширенный взгляд на тему.
Что касается конкретных вопросов:
Это
NumberFormatException
считать проверенным исключением?
Нет.NumberFormatException
не проверено (= является подклассомRuntimeException
). Зачем? Я не знаю. (но должен был быть методisValidInteger(..)
)Является
RuntimeException
непроверенное исключение?
Да, точно.Что мне здесь делать?
Это зависит от того, где находится этот код и что вы хотите сделать. Если он находится на уровне пользовательского интерфейса - поймайте его и покажите предупреждение; если он находится в слое обслуживания - вообще не улавливай - пусть он пузырится. Только не глотай исключение. Если в большинстве случаев возникает исключение, вы должны выбрать один из них:- войдите и вернитесь
- сбросить его (объявить его методом)
- создать новое исключение, передав текущее в конструктор
Теперь, не может ли приведенный выше код быть проверенным исключением? Я могу попытаться восстановить ситуацию, как это? Могу я?
Это могло бы быть. Но ничто не мешает вам поймать и непроверенное исключениеПочему люди добавляют класс
Exception
в пункте о бросках?
Чаще всего потому, что людям лень думать, что ловить и что отбрасывать. БросаниеException
это плохая практика и ее следует избегать.
Увы, нет единого правила, которое позволяло бы вам определять, когда отлавливать, когда перебрасывать, когда использовать проверенный и когда использовать непроверенные исключения. Я согласен, что это вызывает много путаницы и много плохого кода. Общий принцип сформулирован Блохом (вы процитировали его часть). И общий принцип заключается в том, чтобы выбросить исключение для слоя, где вы можете его обработать.
То, является ли что-то "проверенным исключением", не имеет никакого отношения к тому, поймали ли вы это или что вы делаете в блоке catch. Это свойство классов исключений. Все, что является подклассом Exception
кроме RuntimeException
и его подклассы - проверенное исключение.
Компилятор Java заставляет вас перехватывать проверенные исключения или объявлять их в сигнатуре метода. Предполагалось, что это повысит безопасность программы, но большинство считает, что оно не стоит тех проблем с дизайном, которые оно создает.
Почему они позволяют всплыть исключение? Разве не справиться с ошибкой, чем раньше, тем лучше? Зачем пузыриться?
Потому что это все исключение. Без этой возможности вам не понадобятся исключения. Они позволяют вам обрабатывать ошибки на выбранном вами уровне, а не заставлять вас обрабатывать их низкоуровневыми методами, где они изначально возникали.
Вышеуказанное считается проверенным исключением? Нет Тот факт, что вы обрабатываете исключение, не делает его проверенным исключением, если оно является RuntimeException.
Является ли RuntimeException непроверенным исключением? да
Проверенные исключения являются подклассами java.lang.Exception Не отмеченные исключения являются подклассами java.lang.RuntimeException
Вызовы, выбрасывающие проверенные исключения, должны быть заключены в блок try{} или обработаны на уровне выше в вызывающей стороне метода. В этом случае текущий метод должен объявить, что он выбрасывает указанные исключения, чтобы вызывающие могли принять соответствующие меры для обработки исключения.
Надеюсь это поможет.
Q: я должен всплыть точное исключение или замаскировать его с помощью исключения?
A: Да, это очень хороший вопрос и важное соображение дизайна. Класс Exception является очень общим классом исключений и может использоваться для переноса внутренних исключений низкого уровня. Вам лучше создать собственное исключение и обернуть его внутри. Но, и главное: никогда не скрывать первопричину. Например, Dont ever
делать следующее -
try {
attemptLogin(userCredentials);
} catch (SQLException sqle) {
throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}
Вместо этого сделайте следующее:
try {
attemptLogin(userCredentials);
} catch (SQLException sqle) {
throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}
Уничтожение первоначальной первопричины скрывает фактическую причину, выходящую за рамки восстановления, - это кошмар для рабочих групп поддержки, которым все, что им предоставляется, - это журналы приложений и сообщения об ошибках. Хотя последний вариант лучше, но многие люди не часто его используют, потому что разработчики просто не могут передать исходное сообщение вызывающей стороне. Так что сделайте твердое замечание: Always pass on the actual exception
обратно вне зависимости от того, включено или нет в какое-либо исключение для конкретного приложения
При попытке поймать RuntimeExceptions
RuntimeExceptions, как общее правило, не следует пытаться поймать. Они обычно сигнализируют об ошибке программирования и должны быть оставлены в покое. Вместо этого программист должен проверить состояние ошибки, прежде чем вызывать некоторый код, который может привести к RuntimeException. Например:
try {
setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} catch (NullPointerException npe) {
sendError("Sorry, your userObject was null. Please contact customer care.");
}
Это плохая практика программирования. Вместо этого нулевая проверка должна была быть сделана как -
if (userObject != null) {
setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
sendError("Sorry, your userObject was null. Please contact customer care.");
}
Но бывают случаи, когда такая проверка ошибок стоит дорого, например, форматирование чисел, подумайте об этом -
try {
String userAge = (String)request.getParameter("age");
userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}
Здесь проверка ошибок перед вызовом не стоит усилий, потому что она по существу означает дублирование всего кода преобразования строки в целое в методе parseInt() - и подвержена ошибкам, если реализована разработчиком. Так что лучше просто покончить с try-catch.
Таким образом, NullPointerException и NumberFormatException являются RuntimeException, поэтому перехват NullPointerException должен быть заменен изящной нулевой проверкой, в то время как я рекомендую явно перехватывать NumberFormatException, чтобы избежать возможного введения подверженного ошибкам кода.
1 Если вы не уверены в исключении, проверьте API:
java.lang.Object extended by java.lang.Throwable extended by java.lang.Exception extended by java.lang.RuntimeException //<-NumberFormatException is a RuntimeException extended by java.lang.IllegalArgumentException extended by java.lang.NumberFormatException
2 Да, и каждое исключение, которое расширяет его.
3 Нет необходимости ловить и бросать одно и то же исключение. В этом случае вы можете показать новый диалог файлов.
4 FileNotFoundException уже является проверенным исключением.
5 Если ожидается, что вызов метода someMethod
чтобы поймать исключение, последний может быть брошен. Это просто "передает мяч". Примером его использования может быть то, что вы хотите добавить его в свои собственные частные методы и вместо этого обработать исключение в вашем открытом методе.
Хорошее чтение - сам документ Oracle: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html
Почему разработчики решили заставить метод указывать все неперехваченные проверенные исключения, которые могут быть выброшены в его пределах? Любое исключение, которое может быть вызвано методом, является частью общедоступного интерфейса программирования метода. Те, кто вызывает метод, должны знать об исключениях, которые может вызвать метод, чтобы они могли решить, что с ними делать. Эти исключения являются такой же частью интерфейса программирования этого метода, как его параметры и возвращаемое значение.
Следующий вопрос может быть следующим: "Если так хорошо документировать API метода, включая исключения, которые он может генерировать, почему бы не указать также исключения времени выполнения?" Исключения во время выполнения представляют проблемы, которые являются результатом программной проблемы, и, как таковой, нельзя ожидать, что клиентский код API восстановит их или обработает их каким-либо образом. Такие проблемы включают арифметические исключения, такие как деление на ноль; исключения указателя, такие как попытка доступа к объекту через нулевую ссылку; и индексация исключений, таких как попытка доступа к элементу массива через индекс, который слишком велик или слишком мал.
Также есть важная информация в спецификации языка Java:
Проверенные классы исключений, названные в предложении throws, являются частью договора между разработчиком и пользователем метода или конструктора.
Суть ИМХО в том, что вы можете поймать любого RuntimeException
, но от вас не требуется и, фактически, реализация не обязана поддерживать те же самые непроверенные исключения, которые не являются частью договора.
1) Нет, NumberFormatException является непроверенным исключением. Даже если вы поймали это (вы не обязаны), это не проверяется. Это потому, что это подкласс IllegalArgumentException, который является подклассом RuntimeException.
2) RuntimeException является корнем всех непроверенных исключений. Каждый подкласс RuntimeException не проверяется. Все остальные исключения и Throwables проверяются, за исключением ошибок (которые подпадают под Throwable).
3/4) Вы можете предупредить пользователя, что он выбрал несуществующий файл, и попросить новый. Или просто выйдите, сообщив пользователю, что он ввел что-то недействительное.
5) Бросать и ловить "Исключение" - плохая практика. Но в более общем случае вы можете выдать другие исключения, чтобы вызывающий мог решить, как с этим справиться. Например, если вы написали библиотеку для обработки чтения какого-либо файла и ваш метод был передан несуществующему файлу, вы не знаете, как с этим справиться. Звонящий хочет спросить снова или выйти? Таким образом, вы бросаете исключение вверх по цепочке к вызывающей стороне.
Во многих случаях возникает непроверенное исключение, потому что программист не проверял входные данные (в случае NumberFormatException в вашем первом вопросе). Вот почему их необязательно ловить, потому что есть более элегантные способы избежать создания этих исключений.
Проверено - склонен случиться. Проверено во время компиляции.
Например, FileOperations
Не проверено - из-за неверных данных. Проверено во время выполнения.
Например..
String s = "abc";
Object o = s;
Integer i = (Integer) o;
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at Sample.main(Sample.java:9)
Здесь исключение связано с неверными данными и никоим образом не может быть определено во время компиляции.
Исключения во время выполнения Исключения во время выполнения называются непроверенными исключениями. Все остальные исключения являются проверенными исключениями, и они не являются производными от java.lang.RuntimeException.
Проверенные исключения Проверенное исключение должно быть зафиксировано где-то в вашем коде. Если вы вызываете метод, который выдает проверенное исключение, но вы где-то не перехватываете проверенное исключение, ваш код не будет компилироваться. Вот почему они называются проверенными исключениями: компилятор проверяет, что они обработаны или объявлены.
Ряд методов в Java API генерирует проверенные исключения, поэтому вы часто будете писать обработчики исключений, чтобы справиться с исключениями, сгенерированными методами, которые вы не написали.
Чтобы ответить на последний вопрос (другие, кажется, полностью ответили выше), "Должен ли я выдать точное исключение или замаскировать его с помощью исключения?"
Я предполагаю, что вы имеете в виду что-то вроде этого:
public void myMethod() throws Exception {
// ... something that throws FileNotFoundException ...
}
Нет, всегда объявляйте самое точное возможное исключение или список таких. Исключения, которые вы объявляете своим методом как способный к выбросу, являются частью контракта между вашим методом и вызывающей стороной. Бросок "FileNotFoundException" означает, что возможно, что имя файла неверно и файл не будет найден; звонящий должен будет разобраться с этим разумно. Бросок "Исключение" означает "Эй, дерьмо случается. Сделка". Это очень плохой API.
В комментариях к первой статье есть несколько примеров, когда "throws Exception" является допустимым и разумным объявлением, но это не относится к большинству "нормальных" кодов, которые вы когда-либо будете писать.
Я думаю, что проверенные исключения являются хорошим напоминанием для разработчика, использующего внешнюю библиотеку, о том, что в исключительных ситуациях могут возникнуть проблемы с кодом из этой библиотеки.
Узнайте больше о проверенных и непроверенных исключениях здесь http://learnjava.today/2015/11/checked-vs-unchecked-exceptions/
Проверенные исключения проверяются во время компиляции JVM и связаны с ресурсами (файлы / db / stream / socket и т. Д.). Мотив проверенного исключения состоит в том, что во время компиляции, если ресурсы недоступны, приложение должно определить альтернативное поведение для обработки этого в блоке catch / finally.
Непроверенные исключения - это чисто программные ошибки, неправильные вычисления, нулевые данные или даже сбои в бизнес-логике могут привести к исключениям во время выполнения. Абсолютно хорошо обрабатывать / перехватывать непроверенные исключения в коде.
Объяснение взято с http://coder2design.com/java-interview-questions/
Мое безусловное любимое описание различий между непроверенными и проверенными исключениями предоставлено в статье из учебника по Java " Непроверенные исключения - противоречие " (извините, что все элементарное в этом посте - но, эй, основы иногда бывают лучшими):
Вот практический совет: если разумно ожидать, что клиент восстановится после исключения, сделайте его проверенным исключением. Если клиент не может ничего сделать для восстановления из исключения, сделайте его непроверенным исключением
Сердце "какого типа исключения генерировать" является семантическим (до некоторой степени), и приведенная выше цитата обеспечивает превосходное руководство (следовательно, я все еще поражаюсь представлению о том, что C# избавился от проверенных исключений - особенно, как утверждает Лисков для их полезность).
Остальное становится логичным: на какие исключения компилятор ожидает от меня явного ответа? Те, от которых вы ожидаете, что клиент восстановится.
Я просто хочу добавить некоторые соображения, чтобы вообще не использовать проверенные исключения. Это не полный ответ, но я чувствую, что он отвечает на часть вашего вопроса и дополняет многие другие ответы.
Всякий раз, когда проверяются исключения, есть throws CheckedException
где-то в сигнатуре метода (CheckedException
может быть любое проверенное исключение). Сигнатура НЕ выбрасывает исключение, исключение является аспектом реализации. Интерфейсы, сигнатуры методов, родительские классы, все это НЕ должно зависеть от их реализации. Использование проверенных исключений здесь (на самом деле тот факт, что вы должны объявить throws
в сигнатуре метода) связывает ваши высокоуровневые интерфейсы с вашими реализациями этих интерфейсов.
Позвольте мне показать вам пример.
Давайте иметь хороший и чистый интерфейс, как это
public interface IFoo {
public void foo();
}
Теперь мы можем написать много реализаций метода foo()
, как это
public class Foo implements IFoo {
@Override
public void foo() {
System.out.println("I don't throw and exception");
}
}
Класс Foo отлично подойдет. Теперь давайте сделаем первую попытку в классе Bar
public class Bar implements IFoo {
@Override
public void foo() {
//I'm using InterruptedExcepton because you probably heard about it somewhere. It's a checked exception. Any checked exception will work the same.
throw new InterruptedException();
}
}
Этот класс Bar не будет компилироваться. Поскольку InterruptedException является проверенным исключением, вы должны либо перехватить его (с помощью try-catch внутри метода foo()), либо объявить, что вы его выбросили (добавив throws InterruptedException
подписи метода). Поскольку я не хочу фиксировать это исключение здесь (я хочу, чтобы оно распространялось вверх, чтобы я мог правильно с ним справиться где-то еще), давайте изменим сигнатуру.
public class Bar implements IFoo {
@Override
public void foo() throws InterruptedException {
throw new InterruptedException();
}
}
Этот класс Bar тоже не скомпилируется! Метод Бар foo () НЕ переопределяет метод IFoo foo (), так как их сигнатуры разные. Я мог бы удалить аннотацию @Override, но я хочу программировать на интерфейс IFoo как IFoo foo;
а затем решить, какую реализацию я хочу использовать, например, foo = new Bar();
, Если метод Бар foo () не переопределяет метод IFoo IFoo, когда я делаю foo.foo();
это не вызовет реализацию Баром foo().
Сделать бар public void foo() throws InterruptedException
переопределить IFoo's public void foo()
Я ДОЛЖЕН добавить throws InterruptedException
к сигнатуре метода IFoo. Это, однако, вызовет проблемы с моим классом Foo, поскольку его сигнатура метода foo () отличается от сигнатуры метода IFoo. Кроме того, если бы я добавил throws InterruptedException
к методу Foo foo () Я бы получил еще одну ошибку, утверждая, что метод Foo foo () объявляет, что он генерирует InterruptedException, но никогда не генерирует InterruptedException.
Как вы можете видеть (если я проделал приличную работу по объяснению этого материала), тот факт, что я выбрасываю проверенное исключение, такое как InterruptedException, заставляет меня привязывать мой интерфейс IFoo к одной из его реализаций, что, в свою очередь, вызывает хаос в IFoo. другие реализации!
Это одна из основных причин, почему проверенные исключения являются ПЛОХОЙ. В шапках.
Одно из решений состоит в том, чтобы перехватить проверенное исключение, поместить его в непроверенное исключение и выдать непроверенное исключение.
- Java различает две категории исключений (проверено и не проверено)
- Java применяет улов или объявленное требование для проверенных исключений
- Тип исключения определяет, будет ли исключение отмечено или не отмечено.
- Все типы исключений, которые являются прямыми или косвенными подклассами класса RuntimeException, являются непроверенными исключениями.
- Все классы, которые наследуются от класса Exception, но не RuntimeException, считаются проверенными исключениями.
- Классы, которые наследуются от класса Error, считаются непроверенными.
- Компилятор проверяет каждый вызов метода и замедление, чтобы определить, вызывает ли метод проверенное исключение.
- Если это так, компилятор гарантирует, что исключение будет перехвачено или объявлено в предложении throws.
- Чтобы удовлетворить объявленную часть требования catch-or-Declare, метод, который генерирует исключение, должен предоставить предложение throws, содержащее зарегистрированное исключение.
- Классы исключений определяются для проверки, когда они считаются достаточно важными для отлова или объявления.
Почему они позволяют всплыть исключение? Разве обработка ошибок не быстрее, лучше? Зачем пузыриться?
Например, допустим, у вас есть какое - то клиент-серверное приложение, и клиент отправил запрос на какой-то ресурс, который не может быть обнаружен, или на что-то другое, возможно, произошла ошибка на стороне сервера при обработке запроса пользователя, тогда это является обязанностью. сервера, чтобы сообщить клиенту, почему он не может получить то, что он запрашивал, поэтому для достижения этого на стороне сервера пишется код для выброса исключения с использованием ключевого слова throw вместо его проглатывания или обработки. если сервер обрабатывает его / ласточку это, тогда не будет никакой возможности сообщить клиенту, какая ошибка произошла.
Примечание. Чтобы дать четкое описание того, какой тип ошибки произошел, мы можем создать наш собственный объект Exception и передать его клиенту.
Просто для того, чтобы указать, что если вы бросите проверенное исключение в коде, а улов будет на несколько уровней выше, вам необходимо объявить исключение в сигнатуре каждого метода между вами и уловом. Таким образом, инкапсуляция нарушена, потому что все функции в пути throw должны знать о деталях этого исключения.
Короче говоря, исключения, которые ваш модуль или модули выше должны обрабатывать во время выполнения, называются проверочными исключениями, другие - непроверенными исключениями, которые либо RuntimeException
или же Error
, В этом видео он объясняет проверенные и непроверенные исключения в Java. https://www.youtube.com/watch?v=ue2pOqLaArw
Вот простое правило, которое может помочь вам решить. Это связано с тем, как интерфейсы используются в Java.
Возьмите свой класс и представьте, что вы разрабатываете интерфейс для него таким образом, чтобы интерфейс описывал функциональные возможности класса, но не основную реализацию (как должен делать интерфейс). Представьте, что вы могли бы реализовать класс другим способом.
Посмотрите на методы интерфейса и рассмотрите исключения, которые они могут выдавать:
Если метод может вызвать исключение, независимо от базовой реализации (другими словами, он описывает только функциональные возможности), то это, вероятно, должно быть проверенное исключение в интерфейсе.
Если исключение вызвано базовой реализацией, оно не должно быть в интерфейсе. Следовательно, это должно быть либо непроверенное исключение в вашем классе (поскольку непроверенные исключения не должны появляться в сигнатуре интерфейса), либо вы должны обернуть его и повторно обработать как проверенное исключение, которое является частью метода интерфейса.
Чтобы решить, следует ли вам переносить и перебрасывать, вам следует снова подумать о том, имеет ли смысл пользователю интерфейса обрабатывать условие исключения немедленно, или исключение настолько общее, что вы ничего не можете с этим поделать, и оно должно распространять вверх по стеку. Имеет ли смысл обернутое исключение, когда оно выражается как функциональность нового интерфейса, который вы определяете, или это просто носитель для пакета возможных состояний ошибки, которые также могут случиться с другими методами? Если первое, оно все еще может быть проверенным исключением, в противном случае его следует отключить.
Обычно вы не должны планировать "всплывать" исключения (ловить и отбрасывать). Либо исключение должно быть обработано вызывающей стороной (в этом случае оно проверено), либо оно должно пройти весь путь до высокоуровневого обработчика (в этом случае это проще всего, если оно не проверено).
Все это проверенные исключения. Непроверенные исключения являются подклассами RuntimeException. Решение не в том, как с ними обращаться, а в том, что ваш код их выбрасывает. Если вы не хотите, чтобы компилятор сообщал вам, что вы не обработали исключение, используйте исключение без проверки (подкласс RuntimeException). Они должны быть сохранены для ситуаций, которые вы не можете восстановить, например, из-за нехватки памяти и т.п.
Проверенные исключения:
Исключения, которые проверяются компилятором для плавного выполнения программы во время выполнения, называются Checked Exception.
Это происходит во время компиляции.
- Если они не обрабатываются должным образом, они приведут к ошибке времени компиляции (не исключение).
Все подклассы класса Exception, кроме RuntimeException, являются проверенными исключениями.
Гипотетический пример. Предположим, вы выходите из дома на экзамен, но если вы проверите, взяли ли вы свой билет в зал дома (время компиляции), то в экзаменационном зале проблем не возникнет (время выполнения).
Непроверенное исключение:
Исключения, которые не проверяются компилятором, называются непроверенными исключениями.
Это происходит во время выполнения.
Если эти исключения не обрабатываются должным образом, они не дают ошибку времени компиляции. Но программа будет прервана преждевременно во время выполнения.
Все подклассы RunTimeException и Error являются непроверенными исключениями.
Гипотетический пример. Предположим, что вы находитесь в своем экзаменационном зале, но каким-то образом в вашей школе произошла пожарная авария (имеется в виду во время выполнения), когда вы ничего не можете сделать в это время, но меры предосторожности могут быть сделаны раньше (время компиляции).
Если кому-то нужно еще одно доказательство неприязни к проверенным исключениям, посмотрите первые несколько абзацев популярной библиотеки JSON:
"Хотя это проверенное исключение, его редко можно восстановить. Большинству абонентов следует просто обернуть это исключение в неконтролируемое исключение и повторно обработать его".
Так почему же кто-то заставляет разработчиков продолжать проверять исключение, если вместо этого мы должны просто "обернуть его"? лол
http://developer.android.com/reference/org/json/JSONException.html
Все исключения должны быть проверены исключения.
Непроверенные исключения - неограниченные случаи. И неограниченные gotos считаются плохой вещью.
Непроверенные исключения нарушают инкапсуляцию. Чтобы правильно их обрабатывать, все функции в дереве вызовов между метателем и ловцом должны быть известны, чтобы избежать ошибок.
Исключением являются ошибки в функции, которая их генерирует, но не ошибки в функции, которая их обрабатывает. Цель исключений - дать программе второй шанс, отложив решение о том, является ли это ошибкой или нет, в другой контекст. Только в другом контексте может быть принято правильное решение.