Понимание проверенных и непроверенных исключений в Java - PullRequest
658 голосов
/ 24 мая 2011

Джошуа Блох в « Effective Java » сказал, что

Используйте проверенные исключения для восстанавливаемых условий и исключения времени выполнения для ошибок программирования (Элемент 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.Должен ли я вспомнить точное исключение или замаскировать его с помощью исключения?

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

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

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

Ответы [ 21 ]

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

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

Всякий раз, когда включаются проверенные исключения, где-то в сигнатуре метода есть 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 foo, то когда я делаю foo.foo();, он не будет вызывать реализацию Баром foo ().

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

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

Это одна из причин, почему проверенные исключения являются ПЛОХОЙ.В заглавных буквах.

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

1 голос
/ 04 августа 2014

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

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

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

1 голос
/ 06 ноября 2015

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

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

1 голос
/ 20 марта 2018

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

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

1 голос
/ 15 января 2015

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

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

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

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

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

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

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

1 голос
/ 19 октября 2016

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

0 голосов
/ 01 февраля 2018

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

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

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

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

0 голосов
/ 09 января 2018

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

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

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

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

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

Исключение не проверено :

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

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

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

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

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

0 голосов
/ 24 мая 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...