Джошуа Блох в « Эффективной Яве » сказал, что
Используйте проверенные исключения для восстанавливаемых условий и исключения времени выполнения для ошибок программирования (Элемент 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{
}
Почему они позволяют всплыть исключение? Разве обработка ошибок не быстрее, лучше? Зачем пузыриться?
6. Должен ли я выдать точное исключение или замаскировать его с помощью исключения?
Ниже мои чтения
DataSeries
класс, который содержит данные, которые всегда должны оставаться в порядке времени. Есть способ добавить новыйDataPoint
в конецDataSeries
. Если весь мой код работает правильно на протяжении всего проекта,DataPoint
никогда не следует добавлять в конец, который имеет более раннюю дату, чем тот, который уже находится в конце. Каждый модуль во всем проекте построен с этим трюизмом. Однако я проверяю это условие и выкидываю непроверенное исключение, если это происходит. Почему? Если это произойдет, я хочу знать, кто это делает, и исправить это.Ответы:
Многие люди говорят, что проверенные исключения (то есть те, которые вы должны явно перехватить или перебросить) не должны использоваться вообще. Например, они были устранены в C #, и большинство языков не имеют их. Таким образом, вы всегда можете бросить подкласс
RuntimeException
(непроверенное исключение)Тем не менее, я думаю, что проверенные исключения полезны - они используются, когда вы хотите заставить пользователя вашего API думать, как справляться с исключительной ситуацией (если ее можно восстановить). Просто проверенные исключения чрезмерно используются в платформе Java, что заставляет людей ненавидеть их.
Вот мой расширенный взгляд на тему .
Что касается конкретных вопросов:
Является ли
NumberFormatException
рассматриваемое исключение проверенным?Номер
NumberFormatException
не отмечен (= является подклассомRuntimeException
). Почему? Я не знаю. (но должен был быть методisValidInteger(..)
)Это
RuntimeException
непроверенное исключение?Да, точно.
Что мне здесь делать?
Это зависит от того, где находится этот код и что вы хотите сделать. Если он находится на уровне пользовательского интерфейса - поймайте его и покажите предупреждение; если он находится в слое обслуживания - вообще не улавливайте - пусть он пузырится. Только не глотай исключение. Если в большинстве случаев возникает исключение, вы должны выбрать один из них:
Не может ли приведенный выше код быть проверенным исключением? Я могу попытаться восстановить ситуацию, как это? Могу я?
Это могло бы быть. Но ничто не мешает вам поймать и непроверенное исключение
Почему люди добавляют класс
Exception
в предложении throws?Чаще всего потому, что людям лень думать, что ловить и что отбрасывать. Бросать
Exception
- плохая практика, и ее следует избегать.Увы, нет единого правила, которое позволяло бы вам определять, когда отлавливать, когда перебрасывать, когда использовать проверенный и когда использовать непроверенные исключения. Я согласен, что это вызывает много путаницы и много плохого кода. Общий принцип сформулирован Блохом (вы процитировали его часть). И общий принцип заключается в том, чтобы выбросить исключение для слоя, где вы можете его обработать.
источник
То, является ли что-то «проверенным исключением», не имеет никакого отношения к тому, поймали ли вы это или что вы делаете в блоке catch. Это свойство классов исключений. Все , что подкласс
Exception
кроме дляRuntimeException
и его подклассы является проверяемым исключением.Компилятор Java заставляет вас перехватывать проверенные исключения или объявлять их в сигнатуре метода. Предполагалось, что это повысит безопасность программы, но большинство считает, что оно не стоит тех проблем с дизайном, которые оно создает.
Потому что вся точка исключений. Без этой возможности вам не понадобятся исключения. Они позволяют вам обрабатывать ошибки на выбранном вами уровне, а не заставлять вас обрабатывать их низкоуровневыми методами, где они изначально возникали.
источник
Throwable
сказано в javadoc : «Throwable и любой подкласс Throwable, который также не является подклассом ни RuntimeException, ни Error, рассматриваются как проверенные исключения»Вышеуказанное считается проверенным исключением? Нет Тот факт, что вы обрабатываете исключение, не делает его a,
Checked Exception
если оно естьRuntimeException
.Есть ? да
RuntimeException
unchecked exception
Checked Exceptions
являютсяsubclasses
вjava.lang.Exception
Unchecked Exceptions
этоsubclasses
изjava.lang.RuntimeException
Вызовы, выбрасывающие проверенные исключения, должны быть заключены в блок try {} или обработаны на уровне выше в вызывающей стороне метода. В этом случае текущий метод должен объявить, что он выбрасывает указанные исключения, чтобы вызывающие могли принять соответствующие меры для обработки исключения.
Надеюсь это поможет.
A: Да, это очень хороший вопрос и важное соображение дизайна. Класс Exception является очень общим классом исключений и может использоваться для переноса внутренних исключений низкого уровня. Вам лучше создать собственное исключение и обернуть его внутри. Но, и главное - никогда не скрывать первопричину первопричины. Например,
Don't ever
сделайте следующее -Вместо этого сделайте следующее:
Уничтожение первоначальной первопричины скрывает фактическую причину, выходящую за рамки восстановления, - это кошмар для рабочих групп поддержки, которым все, что им предоставляется, это журналы приложений и сообщения об ошибках. Хотя последний вариант лучше, но многие люди не используют его часто, потому что разработчики просто не могут передать исходное сообщение вызывающей стороне. Так что сделайте твердое замечание:
Always pass on the actual exception
вернитесь или нет, завернутый в какое-либо конкретное приложение исключение.RuntimeException
s, как правило, не следует пытаться поймать. Они обычно сигнализируют об ошибке программирования и должны быть оставлены в покое. Вместо этого программист должен проверить состояние ошибки, прежде чем вызывать некоторый код, который может привести кRuntimeException
. Например:Это плохая практика программирования. Вместо этого нулевая проверка должна была быть сделана как -
Но бывают случаи, когда такая проверка ошибок стоит дорого, например, форматирование чисел, подумайте об этом -
Здесь проверка ошибок перед вызовом не стоит усилий, потому что по сути это означает дублирование всего кода преобразования строки в целое внутри метода parseInt () - и подвержена ошибкам, если реализована разработчиком. Так что лучше просто покончить с try-catch.
Так
NullPointerException
иNumberFormatException
естьRuntimeExceptions
, перехватNullPointerException
должен заменяться изящной нулевой проверкой, в то время как я рекомендую перехватыватьNumberFormatException
явно, чтобы избежать возможного введения подверженного ошибкам кода.источник
exception
, я должен всплыть точное исключение или замаскировать его, используяException
. Я пишу код поверх какого-то унаследованного кода, и меняException
везде переполняют. Интересно, это правильное поведение?LoginFailureException(sqle)
?LoginFailureException
расширяетException
и объявляет конструкторpublic LoginFailureException(Throwable cause) { super(cause) }
1 Если вы не уверены в исключении, проверьте API:
2 Да, и каждое исключение, которое расширяет его.
3 Нет необходимости ловить и бросать одно и то же исключение. В этом случае вы можете показать новый диалог файлов.
4 FileNotFoundException это уже проверено исключение.
5 Если ожидается, что метод, вызывающий
someMethod
для исключения, последнее может быть сгенерировано. Это просто "передает мяч". Примером его использования может быть, если вы хотите добавить его в свои собственные частные методы и вместо этого обработать исключение в вашем открытом методе.Хорошее чтение - сам документ Oracle: http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html
Также есть важная информация в спецификации языка Java :
Суть ИМХО в том, что вы можете поймать любое
RuntimeException
, но вы не обязаны и, фактически, реализация не обязана поддерживать те же самые непроверенные исключения, которые не были включены в контракт.источник
exception
, я должен всплыть точное исключение или замаскировать его, используяException
. Я пишу код поверх какого-то унаследованного кода, и меняException
везде переполняют. Интересно, это правильное поведение?1) Нет, NumberFormatException является непроверенным исключением. Даже если вы поймали это (вы не обязаны), потому что это не проверено. Это потому, что это подкласс,
IllegalArgumentException
который является подклассомRuntimeException
.2)
RuntimeException
является корнем всех непроверенных исключений. Каждый подклассRuntimeException
не проверяется. Все остальные исключения иThrowable
проверяются за исключением ошибок (которые подпадают подThrowable
).3/4) Вы можете предупредить пользователя, что он выбрал несуществующий файл, и попросить новый. Или просто выйдите, сообщив пользователю, что он ввел что-то недействительное.
5) Бросать и ловить
'Exception'
- плохая практика. Но в более общем случае вы можете выдать другие исключения, чтобы вызывающий мог решить, как с этим справиться. Например, если вы написали библиотеку для обработки чтения какого-либо файла и ваш метод был передан несуществующему файлу, вы не знаете, как с этим справиться. Звонящий хочет спросить снова или выйти? Таким образом, вы бросаете исключение вверх по цепочке к вызывающей стороне.Во многих случаях
unchecked Exception
происходит, потому что программист не проверял входные данные (в случаеNumberFormatException
в вашем первом вопросе). Вот почему их необязательно ловить, потому что есть более изящные способы избежать создания этих исключений.источник
exception
, я должен всплыть точное исключение или замаскировать его, используяException
. Я пишу код поверх какого-то унаследованного кода, и меняException
везде переполняют. Интересно, это правильное поведение?Проверено - Скорее всего. Проверено во время компиляции.
Например. FileOperations
Не проверено - из-за неверных данных. Проверено во время выполнения.
Например..
Здесь исключение связано с неверными данными и никоим образом не может быть определено во время компиляции.
источник
Проверенные исключения проверяются во время компиляции JVM и связаны с ресурсами (файлы / db / stream / socket и т. Д.). Мотив проверенного исключения заключается в том, что во время компиляции, если ресурсы недоступны, приложение должно определить альтернативное поведение для обработки этого в блоке catch / finally.
Непроверенные исключения - это чисто программные ошибки, неправильные вычисления, нулевые данные или даже сбои в бизнес-логике могут привести к исключениям во время выполнения. Абсолютно хорошо обрабатывать / перехватывать непроверенные исключения в коде.
Объяснение взято с http://coder2design.com/java-interview-questions/
источник
Мое абсолютно любимое описание различий между непроверенными и проверенными исключениями предоставлено в статье из учебника по Java « Непроверенные исключения - противоречие » (извините, что все элементарное в этом посте - но, эй, основы иногда бывают лучшими):
Суть "какого типа исключения генерировать" является семантической (в некоторой степени), и приведенная выше цитата обеспечивает превосходное руководство (следовательно, я все еще поражаюсь представлению о том, что C # избавился от проверенных исключений - особенно, как утверждает Лисков для их полезность).
Все остальное становится логичным: на какие исключения компилятор ожидает от меня явного ответа? Те, от которых вы ожидаете, что клиент восстановится.
источник
Чтобы ответить на последний вопрос (другие, кажется, полностью ответили выше), «Должен ли я выдать точное исключение или замаскировать его с помощью исключения?»
Я предполагаю, что вы имеете в виду что-то вроде этого:
Нет, всегда объявляйте наиболее точное возможное исключение или список таких. Исключения, которые вы объявляете для вашего метода как способного к выбросу, являются частью контракта между вашим методом и вызывающей стороной. Бросок
"FileNotFoundException"
означает, что возможно, имя файла недействительно и файл не будет найден; звонящий должен будет разобраться с этим разумно. БросокException
означает «Эй, дерьмо случается. Сделка». Который очень беденAPI
.В комментариях к первой статье есть несколько примеров, когда «throws
Exception
» является допустимым и разумным объявлением, но это не относится к большинству «normal
» кодов, которые вы когда-либо будете писать.источник
Исключения во время выполнения : исключения во время выполнения называются непроверенными исключениями. Все остальные исключения являются проверенными исключениями, и они не являются производными от java.lang.RuntimeException.
Проверенные исключения : проверенное исключение должно быть зафиксировано где-то в вашем коде. Если вы вызываете метод, который выдает проверенное исключение, но не где-то перехватываете проверенное исключение, ваш код не будет компилироваться. Вот почему они называются проверенными исключениями: компилятор проверяет, что они обработаны или объявлены.
Ряд методов в Java API генерирует проверенные исключения, поэтому вы часто будете писать обработчики исключений, чтобы справляться с исключениями, сгенерированными методами, которые вы не писали.
источник
Почему они позволяют всплыть исключение? Разве обработка ошибок не быстрее, лучше? Зачем пузыриться?
Например, допустим, у вас есть какое - то клиент-серверное приложение, и клиент сделал запрос на какой-то ресурс, который не может быть обнаружен, или на какую-то другую ошибку, которая могла возникнуть на стороне сервера при обработке запроса пользователя, тогда это является обязанностью сервера, чтобы сообщить клиенту, почему он не может получить запрашиваемую вещь, поэтому для достижения этого на стороне сервера пишется код, который выдает исключение, используя throw ключевого слова вместо его проглатывания или обработки. если сервер обрабатывает его / ласточку это, тогда не будет никакой возможности сообщить клиенту, какая ошибка произошла.
Примечание: чтобы дать четкое описание того, какой тип ошибки произошел, мы можем создать наш собственный объект Exception и отправить его клиенту.
источник
Я думаю, что проверенные исключения являются хорошим напоминанием для разработчика, использующего внешнюю библиотеку, о том, что в исключительных ситуациях могут возникнуть проблемы с кодом из этой библиотеки.
Узнайте больше о проверенных и непроверенных исключениях здесь http://learnjava.today/2015/11/checked-vs-unchecked-exceptions/
источник
Я просто хочу добавить некоторые соображения, чтобы вообще не использовать проверенные исключения. Это не полный ответ, но я чувствую, что он отвечает на часть вашего вопроса и дополняет многие другие ответы.
Всякий раз, когда задействованы проверенные исключения,
throws CheckedException
в сигнатуре метода есть место (CheckedException
может быть любое проверенное исключение). Сигнатура НЕ выбрасывает исключение, исключение является аспектом реализации. Интерфейсы, сигнатуры методов, родительские классы, все это НЕ должно зависеть от их реализации. Использование проверенных исключений здесь (фактически тот факт, что вы должны объявитьthrows
в сигнатуре метода) связывает ваши высокоуровневые интерфейсы с вашими реализациями этих интерфейсов.Позвольте мне показать вам пример.
Давайте иметь хороший и чистый интерфейс, как это
Теперь мы можем написать много реализаций метода
foo()
, как этиКласс Foo отлично подойдет. Теперь давайте сделаем первую попытку в классе Bar
Этот класс Bar не будет компилироваться. Поскольку InterruptedException является проверенным исключением, вы должны либо перехватить его (с помощью try-catch внутри метода foo ()), либо объявить, что вы его бросаете (добавляя
throws InterruptedException
в сигнатуру метода). Поскольку я не хочу фиксировать это исключение здесь (я хочу, чтобы оно распространялось вверх, чтобы я мог правильно с ним справиться где-то еще), давайте изменим сигнатуру.Этот класс Bar тоже не скомпилируется! Метод Бар foo () НЕ переопределяет метод IFoo foo (), так как их сигнатуры разные. Я мог бы удалить аннотацию @Override, но я хочу программировать с интерфейсом IFoo like
IFoo foo;
и позже решить, какую реализацию я хочу использовать, напримерfoo = new Bar();
. Если метод Бар foo () не переопределяет метод IFoo IFoo, то когда я это сделаю,foo.foo();
он не вызовет реализацию Баром функции foo ().Чтобы сделать
public void foo() throws InterruptedException
переопределение Баром IFoo,public void foo()
я ДОЛЖЕН добавитьthrows InterruptedException
к сигнатуре метода IFoo. Это, однако, вызовет проблемы с моим классом Foo, поскольку его сигнатура метода foo () отличается от сигнатуры метода IFoo. Кроме того, если бы я добавилthrows InterruptedException
в метод Foo foo (), я получил бы еще одну ошибку, утверждая, что метод Foo foo () объявляет, что он генерирует InterruptedException, но никогда не генерирует InterruptedException.Как вы можете видеть (если я проделал приличную работу по объяснению этого материала), тот факт, что я выбрасываю проверенное исключение, такое как InterruptedException, заставляет меня связывать мой интерфейс IFoo с одной из его реализаций, что, в свою очередь, вызывает хаос в IFoo другие реализации!
Это одна из основных причин, почему проверенные исключения являются ПЛОХОЙ. В шапках.
Одно из решений состоит в том, чтобы перехватить проверенное исключение, поместить его в непроверенное исключение и выдать непроверенное исключение.
источник
throws InterruptedException
в сигнатуру метода IFoo, не бросая ничего в какой-либо реализации. Так что это на самом деле не вызывает никаких проблем. Если в интерфейсе вы делаете каждый бросок сигнатуры методаException
, он просто дает реализации возможность выбрасывать или не генерировать исключение (любое исключение, посколькуException
инкапсулирует все исключения).throw Exception
предложением в их сигнатуре, даже если ваша реализация ничего не выдаст или может быть более конкретное исключение. Но я все еще чувствую, что это хорошая практика - всегда генерировать исключение для метода интерфейса, потому что, опять же, это дает пользователю возможность выбрасывать или не выбрасывать что-либо.subclasses
для класса,RuntimeException
являются непроверенным исключением.Exception
но неRuntimeException
считаютсяchecked exceptions
.checked exception
.throws
предложение, содержащееchecked-exception
.Exception
классы определяются для проверки, когда они считаются достаточно важными для отлова или объявления.источник
Вот простое правило, которое может помочь вам решить. Это связано с тем, как интерфейсы используются в Java.
Возьмите свой класс и представьте, что вы разрабатываете интерфейс для него таким образом, чтобы интерфейс описывал функциональность класса, но не основную реализацию (как должен делать интерфейс). Представьте, что, возможно, вы реализуете класс другим способом.
Посмотрите на методы интерфейса и рассмотрите исключения, которые они могут выдавать:
Если метод может вызвать исключение независимо от базовой реализации (другими словами, он описывает только функциональные возможности), то это, вероятно, должно быть проверенное исключение в интерфейсе.
Если исключение вызвано базовой реализацией, оно не должно быть в интерфейсе. Следовательно, это должно быть либо непроверенное исключение в вашем классе (поскольку непроверенные исключения не должны появляться в сигнатуре интерфейса), либо вы должны обернуть его и повторно обработать как проверенное исключение, которое является частью метода интерфейса.
Чтобы решить, следует ли вам переносить и перебрасывать, вам следует еще раз подумать, имеет ли смысл пользователь интерфейса для немедленной обработки условия исключения, или исключение настолько общее, что вы ничего не можете с этим поделать, и оно должно распространять вверх по стеку. Имеет ли смысл включенное исключение, когда оно выражается в качестве функциональности нового интерфейса, который вы определяете, или это просто носитель для пакета возможных состояний ошибки, которые также могут случиться с другими методами? Если первое, оно все еще может быть проверенным исключением, в противном случае его следует отключить.
Обычно вы не должны планировать «всплывать» исключения (ловить и отбрасывать). Либо исключение должно быть обработано вызывающей стороной (в этом случае оно проверено), либо оно должно пройти весь путь до высокоуровневого обработчика (в этом случае это проще всего, если оно не проверено).
источник
Просто для того, чтобы указать, что если вы добавляете проверенное исключение в код, а улов находится на несколько уровней выше, вам необходимо объявить исключение в сигнатуре каждого метода между вами и уловом. Таким образом, инкапсуляция нарушена, потому что все функции в пути throw должны знать о деталях этого исключения.
источник
Короче говоря, исключения, которые ваш модуль или модули выше должны обрабатывать во время выполнения, называются проверенными исключениями; другие являются непроверенными исключениями, которые являются
RuntimeException
илиError
.В этом видео объясняются отмеченные и непроверенные исключения в Java:
https://www.youtube.com/watch?v=ue2pOqLaArw
источник
Все это проверенные исключения. Непроверенные исключения являются подклассами RuntimeException. Решение не в том, как с ними обращаться, а в том, что ваш код их выбрасывает. Если вы не хотите, чтобы компилятор сообщал вам, что вы не обработали исключение, используйте исключение без проверки (подкласс RuntimeException). Они должны быть сохранены для ситуаций, из которых вы не можете восстановить, например, из-за нехватки памяти и т.п.
источник
Если кому-то нужно еще одно доказательство неприязни к проверенным исключениям, посмотрите первые несколько параграфов популярной библиотеки JSON:
«Хотя это проверенное исключение, его редко можно восстановить. Большинству абонентов следует просто обернуть это исключение в неконтролируемое исключение и повторно обработать его».
Так почему же кто-то может заставить разработчиков продолжать проверять исключение, если вместо этого мы должны просто «обернуть его»? лол
http://developer.android.com/reference/org/json/JSONException.html
источник
Проверенные исключения :
Исключения, которые проверяются компилятором для плавного выполнения программы во время выполнения, называются Checked Exception.
Это происходит во время компиляции.
Все подклассы класса Exception, кроме RuntimeException, являются проверенными исключениями.
Гипотетический пример Предположим, что вы выходите из дома на экзамен, но если вы проверите, взяли ли вы свой билет в зал дома (время компиляции), то в экзаменационном зале проблем не возникнет (время выполнения).
Непроверенное исключение :
Исключения, которые не проверяются компилятором, называются непроверенными исключениями.
Это происходит во время выполнения.
Если эти исключения не обрабатываются должным образом, они не дают ошибку времени компиляции. Но программа будет прервана преждевременно во время выполнения.
Все подклассы RunTimeException и Error являются непроверенными исключениями.
Гипотетический пример. Предположим, вы находитесь в своем экзаменационном зале, но каким-то образом в вашей школе произошел пожар (например, во время выполнения), когда вы ничего не можете сделать в это время, но меры предосторожности могут быть сделаны раньше (время компиляции).
источник
Все исключения должны быть проверены исключения.
Непроверенные исключения - неограниченные переходы. И неограниченные gotos считаются плохой вещью.
Непроверенные исключения нарушают инкапсуляцию. Чтобы правильно их обработать, все функции в дереве вызовов между метателем и ловцом должны быть известны, чтобы избежать ошибок.
Исключением являются ошибки в функции, которая их генерирует, но не ошибки в функции, которая их обрабатывает. Цель исключений - дать программе второй шанс, отложив решение о том, является ли это ошибкой или нет, в другой контекст. Только в другом контексте может быть принято правильное решение.
источник