Понимание проверенных и непроверенных исключений в 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{

}

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

6. Должен ли я вспомнить точное исключение или замаскировать его с помощью исключения?

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

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

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

Ответ 1

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

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

Вот мой расширенный просмотр по теме.

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

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

  • Является ли RuntimeException неконтролируемым исключением?
    Да, точно.

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

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

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

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

Ответ 2

Является ли что-то "проверенным исключением", не имеет никакого отношения к тому, поймаете ли вы его или что вы делаете в блоке catch. Это свойство классов исключений. Все, что является подклассом Exception, за исключением RuntimeException и его подклассов, является проверенным исключением.

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

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

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

Ответ 3

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

  2. Является ли RuntimeException unchecked exception? да

Checked Exceptions являются subclasses java.lang.Exception Unchecked Exceptions являются subclasses java.lang.RuntimeException

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

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

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

A: Да, это очень хороший вопрос и важное соображение дизайна. Класс Exception является очень общим классом исключений и может использоваться для переноса внутренних исключений низкого уровня. Вам лучше создать собственное исключение и обернуть его внутри. Но, и главное: никогда не скрывать первопричину первопричины. Например, Don't 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

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

try {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welcome 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 являются RuntimeExceptions, RuntimeExceptions NullPointerException должен быть заменен изящной нулевой проверкой, в то время как я рекомендую явно NumberFormatException чтобы избежать возможного введения подверженного ошибкам кода.

Ответ 4

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-интерфейс метода, включая исключения, которые он может использовать, почему бы и не указывать исключения времени выполнения?" Исключения в Runtime представляют проблемы, которые являются результатом проблемы программирования, и, как таковой, клиентский код API не может разумно ожидать восстановления от них или для их обработки каким-либо образом. К таким проблемам относятся арифметические исключения, такие как деление на ноль; исключения указателя, например, попытки доступа к объекту посредством нулевой ссылки; и исключения индексирования, такие как попытка доступа к элементу массива через слишком большой или слишком большой индекс.

Также существует важная информация в Спецификация языка Java:

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

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

Ответ 5

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

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

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

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

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

Ответ 6

Проверено - Предполагается, что произойдет. Проверено во время компиляции.

Например, 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)

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

Ответ 7

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

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

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

Ответ 8

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

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

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

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

Ответ 9

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

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

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

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

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

Ответ 10

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

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

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

Ответ 11

  • Java различает две категории исключений (проверено и не проверено).
  • Java применяет улов или объявленное требование для проверенных исключений.
  • Тип исключения определяет, будет ли исключение отмечено или не отмечено.
  • Все типы исключений, которые являются прямыми или косвенными subclasses класса RuntimeException являются непроверенными исключениями.
  • Все классы, которые наследуются от класса Exception но не от RuntimeException, считаются checked exceptions.
  • Классы, которые наследуются от класса Error, считаются непроверенными.
  • Компилятор проверяет каждый вызов метода и замедление, чтобы определить, вызывает ли метод checked exception.
    • В этом случае компилятор гарантирует, что исключение будет перехвачено или объявлено в предложении throws.
  • Чтобы удовлетворить объявленную часть требования catch-or-Declare, метод, который генерирует исключение, должен предоставить предложение throws, содержащее checked-exception.
  • Классы Exception определяются для проверки, когда они считаются достаточно важными для отлова или объявления.

Ответ 12

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

Когда проверяются исключения, существует 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 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 переопределить IFoo public void foo(), я ДОЛЖЕН добавить throws InterruptedException к сигнатуре метода IFoo. Это, однако, вызовет проблемы с моим классом Foo, так как его сигнатура метода foo() отличается от сигнатуры метода IFoo. Кроме того, если бы я добавил throws InterruptedException в метод Foo foo(), я бы получил еще одну ошибку, указав, что метод Foo foo() объявляет, что он генерирует прерывание Exception, но никогда не генерирует прерывание Exception.

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

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

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

Ответ 13

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

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

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

Ответ 14

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

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

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

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

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

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

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

Ответ 15

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

Подробнее о проверенных и непроверенных исключениях читайте здесь http://learnjava.today/2015/11/checked-vs-unchecked-exceptions/

Ответ 16

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

Ответ 17

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

В этом видео объясняются проверенные и непроверенные исключения в Java:
https://www.youtube.com/watch?v=ue2pOqLaArw

Ответ 18

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

Ответ 19

Основное различие между проверенным и неконтролируемым исключением заключается в том, что проверенные исключения проверяются во время компиляции, в то время как исключенные исключения проверяются во время выполнения.

Что такое проверенные исключения? Проверенные исключения проверяются во время компиляции. Это означает, что если метод выбрасывает проверенное исключение, он должен обрабатывать исключение, используя блок try-catch, или должен объявлять исключение, используя ключевое слово throw, иначе программа выдаст ошибку компиляции.

Давайте рассмотрим это с помощью примера:

Проверенный пример исключения В этом примере мы читаем файл myfile.txt и отображаем его содержимое на экране. В этой программе есть три места, где выбрано исключенное исключение, как указано в комментариях ниже. FileInputStream, который используется для указания пути и имени файла, выдает FileNotFoundException. Метод read(), который считывает содержимое файла, генерирует IOException и метод close(), который закрывает входной поток файла, также вызывает исключение IOException.

   import java.io.*;
    class Example {  
    public static void main(String args[]) 
  {
  FileInputStream fis = null;
  /*This constructor FileInputStream(File filename)
 * throws FileNotFoundException which is a checked
 * exception
     */
    fis = new FileInputStream("B:/myfile.txt"); 
  int k; 

  /* Method read() of FileInputStream class also 
throws 
 * a checked exception: IOException
     */
  while(( k = fis.read() ) != -1) 
  { 
    System.out.print((char)k); 
    } 

/*The method close() closes the file input stream
 * It throws IOException*/
   fis.close();     
  }
  }

Вывод:

Исключение в потоке "main" java.lang.Error: нерешенные проблемы компиляции: необработанный тип исключения FileNotFoundException Необработанный тип исключения IOException Необработанный тип исключения IOException Почему эта ошибка компиляции? Как я уже упоминал в начале, проверенные исключения проверяются во время компиляции. Поскольку мы не обрабатывали/не объявляли исключения, наша программа давала ошибку компиляции. Как устранить ошибку? Существует два способа избежать этой ошибки. Мы увидим оба пути один за другим.

Метод 1: объявить исключение, используя ключевое слово throw. Как известно, все три случая отмеченных исключений находятся внутри метода main(), поэтому один из способов избежать ошибки компиляции: объявить исключение в методе, используя ключевое слово throw. Возможно, вы думаете, что наш код бросает FileNotFoundException и IOException и то, почему мы объявляем только IOException. Причина в том, что IOException является родительским классом FileNotFoundException, поэтому он по умолчанию охватывает это. Если вы хотите, вы можете объявить их как это public static void main (String args []), выдает IOException, FileNotFoundException.

   import java.io.*;
   class Example {  
   public static void main(String args[]) throws 
   IOException
   {
  FileInputStream fis = null;
  fis = new FileInputStream("B:/myfile.txt"); 
  int k; 

  while(( k = fis.read() ) != -1) 
  { 
   System.out.print((char)k); 
  } 
  fis.close();  
    }
   }

Выход: содержимое файла отображается на экране.

Способ 2. Обработать их с помощью блоков try-catch. Подход, который мы использовали выше, не очень хорош. Это не лучшая практика обработки исключений. Вы должны дать содержательное сообщение для каждого типа исключения, чтобы кому-то было легко понять эту ошибку. Код должен выглядеть следующим образом:

  import java.io.*;
  class Example {  
  public static void main(String args[])
  {
  FileInputStream fis = null;
  try{
    fis = new FileInputStream("B:/myfile.txt"); 
  }catch(FileNotFoundException fnfe){
        System.out.println("The specified file is not 
   " +
        "present at the given path");
   }
   int k; 
   try{
    while(( k = fis.read() ) != -1) 
    { 
    System.out.print((char)k); 
    } 
    fis.close(); 
    }catch(IOException ioe){
    System.out.println("I/O error occurred: "+ioe);
    }
    }
    }

Этот код будет работать нормально и отобразит содержимое файла.

Вот несколько других проверенных исключений -

SQLException IOException ClassNotFoundException InvocationTargetException Что такое исключенные исключения? Неконтролируемые исключения не проверяются во время компиляции. Это означает, что если ваша программа выбрасывает исключение, и даже если вы не обработали/не объявили это исключение, программа не даст ошибку компиляции. В большинстве случаев это исключение происходит из-за плохих данных, предоставленных пользователем во время взаимодействия с пользовательской программой. Программист должен заранее судить об условиях, которые могут вызывать такие исключения и обрабатывать их надлежащим образом. Все исключенные исключения являются прямыми подклассами класса RuntimeException.

Давайте рассмотрим это на примере:

Непроверенный пример исключения

   class Example {  
   public static void main(String args[])
   {
   int num1=10;
   int num2=0;
   /*Since I'm dividing an integer with 0
   * it should throw ArithmeticException
     */
   int res=num1/num2;
   System.out.println(res);
   }
   }

Если вы скомпилируете этот код, он успешно скомпилируется, но когда вы его запустите, он выбросит ArithmeticException. Это ясно показывает, что неконтролируемые исключения не проверяются во время компиляции, они встречаются во время выполнения. Давайте посмотрим другой пример.

  class Example {  
  public static void main(String args[])
  {
  int arr[] ={1,2,3,4,5};
   /* My array has only 5 elements but we are trying 
   to 
      * display the value of 8th element. It should 
  throw
   * ArrayIndexOutOfBoundsException
     */
  System.out.println(arr[7]);
  }
  }

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

  class Example {  
   public static void main(String args[]) {
  try{
   int arr[] ={1,2,3,4,5};
   System.out.println(arr[7]);
   }
    catch(ArrayIndexOutOfBoundsException e){
   System.out.println("The specified index does not 
   exist " +
    "in array. Please correct the error.");
    }
    }
    }

Вывод:

Указанный индекс не существует в массиве. Исправьте ошибку. Вот несколько неконтролируемых классов исключений:

NullPointerException ArrayIndexOutOfBoundsException ArithmeticException IllegalArgumentException NumberFormatException

Ответ 20

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

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

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

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

Ответ 21

Проверенные исключения:

  • Исключения, которые проверяются компилятором для плавного выполнения программы во время выполнения, называются Checked Exception.

  • Это происходит во время компиляции.

  • Если они не обрабатываются должным образом, они выдадут ошибку времени компиляции (Not Exception).
  • Все подклассы класса Exception, кроме RuntimeException, являются проверенными исключениями.

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

Неконтролируемое исключение:

  • Исключения, которые не проверяются компилятором, называются Unchecked Exceptions.

  • Это происходит во время выполнения.

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

  • Все подклассы RunTimeException и Error являются исключенными исключениями.

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

Ответ 22

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

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

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

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