собственные - Java: проверено на исключение исключения исключений




собственные исключения java (14)

  1. Является ли выше рассмотренное исключение? Нет. Тот факт, что вы обрабатываете исключение, не делает его проверенным исключением, если это исключение RuntimeException.

  2. Исключено ли исключение RuntimeException? да

Проверяемые исключения - это подклассы java.lang.Exception. Непроверенные исключения - это подклассы java.lang.RuntimeException

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

Надеюсь это поможет.

Q: Должен ли я вызывать точное исключение или маскировать его с помощью Exception?

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 () и подвержена ошибкам, если он реализуется разработчиком. Так что лучше просто покончить с попыткой.

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

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

Джошуа Блох в « Эффективной Java » сказал, что

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

Посмотрим, правильно ли я это понимаю.

Вот мое понимание проверенного исключения:

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{

}

Почему они позволяют исключить пузырь? Не лучше ли обрабатывать ошибку раньше? Почему пузыриться?

EDIT: Должен ли я всплывать точное исключение или маскировать его с помощью Exception?

Ниже приведены мои показания

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

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


1) Нет, исключение NumberFormatException является неконтролируемым Исключением. Даже если вы поймали его (вы не обязаны), он не установлен. Это потому, что это подкласс IllegalArgumentException, который является подклассом RuntimeException.

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

3/4). Вы можете предупредить пользователя о том, что они выбрали несуществующий файл и попросят новый. Или просто прекратите информировать пользователя о том, что они ввели что-то недействительное.

5) Бросать и ловить «Исключение» - это плохая практика. Но в более общем плане вы можете использовать другие исключения, чтобы вызывающий мог решить, как с этим бороться. Например, если вы написали библиотеку, чтобы обрабатывать чтение некоторых файлов, и ваш метод был передан несуществующим файлом, вы не знаете, как с этим справиться. Вызывающий абонент хочет снова спросить или уйти? Таким образом, вы бросаете исключение в цепочку обратно к вызывающему.

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


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

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

Вот мой расширенный взгляд на эту тему .

Что касается конкретных вопросов:

  1. Является ли NumberFormatException рассматриваемым исключением?
    Нет. NumberFormatException не NumberFormatException (= является подклассом RuntimeException ). Зачем? Я не знаю. (но должен быть метод isValidInteger(..) )

  2. Исключено ли исключение RuntimeException ?
    Да, точно.

  3. Что мне здесь делать?
    Это зависит от того, где этот код и что вы хотите. Если он находится в слое пользовательского интерфейса - поймайте его и покажите предупреждение; если он находится в сервисном слое - не поймайте его вообще - пусть он пузырится. Просто не проглатывайте исключение. Если в большинстве случаев возникает исключение, вы должны выбрать один из них:

    • зарегистрировать его и вернуть
    • реконструируйте его (объявите его брошенным методом)
    • построить новое исключение, передав текущий в конструкторе
  4. Теперь, не мог ли вышеуказанный код быть проверенным исключением? Я могу попытаться восстановить ситуацию так? Могу я?
    Это могло быть. Но ничто не мешает вам поймать неконтролируемое исключение

  5. Почему люди добавляют класс Exception в предложение throws?
    Чаще всего потому, что люди ленивы, чтобы подумать о том, что поймать и что нужно вернуть. Бросание Exception - плохая практика, и ее следует избегать.

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


Проверенные исключения проверяются во время компиляции JVM и связаны с ресурсами (файлы / db / stream / socket и т. Д.). Мотивом проверенного исключения является то, что во время компиляции, если ресурсы недоступны, приложение должно определить альтернативное поведение для обработки этого в блоке catch / finally.

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

Объяснение взято из http://coder2design.com/java-interview-questions/


Чтобы ответить на окончательный вопрос (остальные, как представляется, полностью ответили выше), «Должен ли я всплывать точное исключение или маскировать его с помощью Исключения?»

Я предполагаю, что вы имеете в виду что-то вроде этого:

public void myMethod() throws Exception {
    // ... something that throws FileNotFoundException ...
}

Нет, всегда указывайте наиболее точное исключение или список таких. Исключения, которые вы объявляете своим методом, способным метать, являются частью контракта между вашим методом и вызывающим. Бросок «FileNotFoundException» означает, что возможно, что имя файла недопустимо, и файл не будет найден; вызывающему нужно будет обращаться с этим разумно. Бросать «Исключение» означает «Эй, sh * t бывает. Сделка». Это очень плохой API.

В комментариях к первой статье есть несколько примеров, где «throws Exception» является допустимым и разумным объявлением, но это не относится к большинству «нормальных» кодов, которые вы когда-либо будете писать.


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

Всякий раз, когда проверяются исключения, возникает 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 тоже не скомпилируется! Метод Bar foo () НЕ переопределяет метод IFoo foo (), поскольку их подписи разные. Я мог бы удалить аннотацию @Override, но я хочу запрограммировать интерфейс IFoo как IFoo foo; а затем принять решение о том, какую реализацию я хочу использовать, например foo = new Bar(); , Если метод Bar foo () не переопределяет метод IFoo foo, когда я делаю foo.foo(); он не будет вызывать реализацию баром foo ().

Чтобы сделать public void foo() throws InterruptedException bar public void foo() throws InterruptedException переопределить public void foo() Ioo, я ДОЛЖЕН добавить throws InterruptedException в подпись метода IFoo. Это, однако, вызовет проблемы с моим классом Foo, так как подпись метода foo () отличается от сигнатуры метода IFoo. Кроме того, если бы я добавил throws InterruptedException в метод Foo foo (), я бы получил еще одну ошибку, указав, что метод Foo foo () объявляет, что он выдает InterruptedException, но он никогда не бросает InterruptedException.

Как вы можете видеть (если я проделал достойную работу по разъяснению этого материала), то факт, что я бросаю проверенное исключение, такое как InterruptedException, заставляет меня привязать мой интерфейс IFoo к одной из его реализаций, что, в свою очередь, приводит к хаосу на IFoo другие реализации!

Это одна важная причина, по которой проверенные исключения BAD. В шапках.

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


Исключения Runtime Исключения исключений Runtime называются исключенными исключениями. Все остальные исключения проверяются исключениями, и они не происходят из java.lang.RuntimeException.

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

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


Почему они позволяют исключить пузырь? Не лучше ли обрабатывать ошибку раньше? Почему пузыриться?

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

Примечание. Чтобы дать четкое описание того, что произошло с ошибкой, мы можем создать собственный объект Exception и передать его клиенту.


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

  1. Непроверенные исключения - это неограниченные пересылки. И неограниченные переселения считаются плохими.

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

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


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

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

Итак, почему в мире кто-нибудь заставит разработчиков продолжать проверять исключение, если мы должны «просто обернуть его» вместо этого? лол

http://developer.android.com/reference/org/json/JSONException.html


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

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

Посмотрите на методы интерфейса и рассмотрите исключения, которые они могут бросить:

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

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

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

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


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


Мое абсолютное любимое описание разницы между отмененными и проверенными исключениями дается в статье «Обучающий курс Java», « Unchecked Exceptions - the Controversy » (извините за то, что все это элементарно на этом посту, но, пожалуй, самые лучшие из них)

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

Сердце «типа исключения для броска» является семантическим (в некоторой степени), и приведенная выше цитата дает и отличную рекомендацию (следовательно, меня все еще смущает представление о том, что C # избавился от проверенных исключений - особенно, поскольку Лисков утверждает их полезность).

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


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





unchecked-exception