Подтвердить что ты не робот

Должен ли класс IOException в Java быть неконтролируемым RuntimeException?

Согласны ли вы с тем, что разработчики Java class java.io.IOException должны были исключить исключение во время выполнения из java.lang.RuntimeException вместо проверяемого исключения, полученного только из java.lang.Exception?

Я думаю, что класс IOException должен был быть неконтролируемым исключением, потому что мало что может сделать приложение для решения таких проблем, как ошибки файловой системы. Однако, в Когда вы не можете выбросить исключение, Elliotte Rusty Harold утверждает, что большинство ошибок ввода-вывода являются временными, поэтому вы можете несколько раз повторить операцию ввода-вывода перед тем, как отказаться:

Например, IOComparator может не допускайте ошибки ввода-вывода, но - потому что многие проблемы ввода-вывода переходный - вы можете повторить несколько раз, как показано в листинге 7:

Это вообще так? Может ли Java-приложение исправлять ошибки ввода-вывода или ждать восстановления системы? Если это так, тогда разумно проверять проверку IOException, но если это не так, тогда IOException следует отключить, чтобы бизнес-логика могла делегировать обработку этого исключения отдельному системному обработчику ошибок.

4b9b3361

Ответ 1

Я совершенно не согласен. Для меня модель правильная. A RuntimeException - это тот, который обычно типично обозначает серьезную ошибку в логике программирования (например, ArrayIndexOutOfBounds, NullPointer или IllegalArgument), или что-то, что в противном случае не было бы определено в среде выполнения (например, SecurityException).

И наоборот, исключение IOException и его производные - это исключения, которые могли бы разумно возникать при нормальном выполнении программы, а общая логика определяла бы, что либо эти проблемы должны быть решены, либо, по крайней мере, программист должен знать, что они могут произойти. Например, в случае с файлами, если ваш регистратор приложений не может записать свои данные, вы скорее будете вынуждены поймать потенциальное исключение IOException и восстановить его или иметь что-то, что может не иметь решающего значения для вашего приложения, сбить всю JVM, потому что никто не думал поймать unchecked Exception (как вы, возможно, догадались, я выберу первое).

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

Насколько вам известно, если система не может восстановиться, всегда есть альтернативы с проверенным исключением. Вы всегда можете, чтобы ваши методы объявляли его в своих бросках, бросали исключение из среды выполнения или приводили в ярость JVM:

public void doit() throws IOException {
  try{
  }catch(IOException e){
    // try to recover
    ...

    // can't recover
    throw e;
  }
}

public void doit() {
  try{
  }catch(IOException e){
    // try to recover
    ...

    // can't recover
    throw new RuntimeException(e);
  }
}



public void doit() {
  try{
  }catch(IOException e){
    // try to recover
    ...

    // OH NO!!!!
    System.exit(Constant.UNRECOVERABLE_IO_ERROR);
  }
}

Ответ 2

Я знаю, что прошло 4 года с тех пор, как этот вопрос был задан, но UncheckedIOException был добавлен в Java 8.

Ответ 3

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

try
{
  methodThatsDeclaredAsThrowingFooExceptionButWont()
}
catch FooException Ex
{
  // Never going to happen
}

Очевидное предположение состоит в том, что, поскольку метод не будет генерировать FooException и единственная причина, по которой catch заключается в том, чтобы сделать компилятор счастливым, нет никаких причин для catch делать что-либо. Коварный, потому что, если a FooException действительно выбрасывается, по какой-то причине он будет оставаться незамеченным.

Альтернативой является метод, который вызывает методThatsDeclaredAsThrowingFooExceptionButWont, чтобы объявить себя как throws FooException или throws Exception, но это тоже не подходит. Если метод, который не ожидается для создания FooException, действительно, состояние системы может отличаться от того, что ожидалось при вызове FooException.

Например, предположим, что одна попытка загрузить документ, но процедура загрузки документа должна читать некоторые таблицы перевода, не относящиеся к документу, которые должны храниться в фиксированном месте; если эта попытка не удалась, просачивание IOException до вызывающего абонента означало бы, что была проблема загрузки загружаемого документа. Если подпрограмма load-document не подготовлена ​​к разумной обработке возможности того, что процедура загрузки таблицы переводов может завершиться неудачно, такой сбой не должен просачиваться так же, как если бы IOException произошел при фактической загрузке документа.

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