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

Мне сказали, что мне следует подумать о том, чтобы выбросить Unchecked exception вместо Checked exception в моем коде, и не только это, но и расширить RuntimeException с помощью мой собственный. Теперь я понимаю разницу между ними, но до сих пор не понимаю, зачем мне это делать?

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

public static Optional<String> getFileMd5(String filePath) throws NoSuchAlgorithmException, IOException {}

Почему я должен заменить их одним (менее подробным) исключением?


person Nimrod    schedule 15.06.2016    source источник
comment
Почему я должен заменить их одним (менее подробным) исключением? Вы не должны. Единственное, на что вы можете заменить их, - это Exception, и это означает, что вы говорите человеку, вызывающему код, что может быть сгенерировано абсолютно любое исключение, и ему придется обрабатывать все исключения соответствующим образом. Это похоже на метод, возвращающий Object: может быть возвращено все, что угодно, поэтому вы должны быть готовы ко всему. Объявление о том, что вы генерируете определенные исключения, означает, что они знают, как их обрабатывать.   -  person Andy Turner    schedule 15.06.2016


Ответы (1)


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

С другой стороны, исключение NoSuchAlgorithmException обязательно должно быть заключено в исключение времени выполнения. У вызывающего абонента нет возможности что-либо сделать, если ваш метод использует алгоритм, которого не существует. Это явно ошибка, если это исключение происходит, и об ошибках следует сигнализировать с помощью исключений времени выполнения. Итак, напишите собственное исключение времени выполнения, которое обертывает исходное исключение NoSuchAlgorithmException (чтобы вы не потеряли основную причину проблемы, если когда-либо ее выбросите), и не беспокоите всех вызывающих ваш код исключением, которое должно никогда, никогда не случится.

Что касается исключений времени выполнения и проверенных исключений, это в основном вопрос, основанный на мнении, но следует отметить несколько вещей:

  • AFAIK, новый Java API больше не использует проверенные исключения. См., Например, java.time, который никогда не генерирует проверенные исключения, хотя старый эквивалент (например, DateFormat) выдает проверенные исключения
  • Java - единственный язык, на котором проверяются исключения.
  • Проверенные исключения плохо сочетаются с функциональными идиомами (лямбда-выражения, потоки и т. Д.), Введенными в Java 8: ни один функциональный интерфейс не генерирует проверенное исключение.

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

Теперь, если ваш вопрос: как генерировать непроверенные исключения, а не проверенные исключения, это довольно просто:

public static Optional<String> getFileMd5(String filePath) {
    try {
        // your original code
    }
    catch (IOException e) {
        throw new UncheckedIOException(e);
    }
    catch (NoSuchAlgorithmException e) {
        throw MyCustomCryptoException(e);
    }
}
person JB Nizet    schedule 15.06.2016