Должен ли класс IOException в Java быть непроверенным RuntimeException? - PullRequest
21 голосов
/ 12 апреля 2010

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

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

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

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

Ответы [ 6 ]

19 голосов
/ 12 апреля 2010

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

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

Я думаю, что есть много ситуаций, в которых 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);
  }
}
15 голосов
/ 14 ноября 2014

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

5 голосов
/ 12 апреля 2010

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

3 голосов
/ 12 апреля 2010

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

2 голосов
/ 12 апреля 2010

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

1 голос
/ 16 февраля 2013

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

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

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

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

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

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

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

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