То, как я могу обработать IOException, который я знаю, никогда не может бросаться безопасным и читаемым способом?

__block Person *aPerson = nil;
20
задан Joachim Sauer 28 April 2011 в 13:15
поделиться

7 ответов

Обычный шаблон для решения этой проблемы - это цепочка исключений . Вы просто оборачиваете FileNotFoundException в RuntimeException:

catch(FileNotFoundException e) {
    throw new RuntimeException(e);
}

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

Правка : Остерегайтесь этого похожего на вид антипаттерна, который я слишком часто видел в дикой природе:

catch(FileNotFoundException e) {
    throw new RuntimeException(e.getMessage());
}

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

Другое редактирование: Как правильно указывает Торбьёрн Равн Андерсен в своем ответе, не повредит указать, почему вы связываете исключение, либо в комментарии, либо, что еще лучше, в виде сообщения об исключении:

catch(FileNotFoundException e) {
    throw new RuntimeException(
        "This should never happen, I know this file exists", e);
}
51
ответ дан 29 November 2019 в 22:31
поделиться

Вы можете преобразовать отмеченное исключение в непроверенное, вложив его в RuntimException. Если исключение обнаружено выше в стеке и выводится с помощью printStackTrace (), также будет отображаться стек для исходного исключения.

try {
    // code...
}
catch (IOException e) {
    throw new RuntimeException(e);
}

Это хорошее решение, которое вы должны без колебаний использовать в таких ситуациях.

11
ответ дан 29 November 2019 в 22:31
поделиться

Рассмотрите возможность использования вместо этого формы

throw new RuntimeException("This should never happen", e);

. Это позволяет вам передать смысл сопровождающему, который будет следовать за вами, как при чтении кода, так и ДОЛЖНО, чтобы исключение произошло в каком-то странном сценарии.

РЕДАКТИРОВАТЬ: Это также хороший способ передать исключения через механизм, не ожидая тех исключений. Например, если у вас есть итератор «получить больше строк из базы данных», интерфейс Iterator не позволяет генерировать, например, исключение FileNotFoundException, поэтому вы можете обернуть его таким образом. В коде ИСПОЛЬЗУЯ итератор, вы можете затем перехватить исключение времени выполнения и проверить исходное исключение с помощью getCause (). ОЧЕНЬ полезно при переходе по устаревшим кодовым путям.

10
ответ дан 29 November 2019 в 22:31
поделиться

Я немного погуглил и нашел этот кусок кода. Мне кажется, это более гибкий подход

Комплименты этой статье

class SomeOtherException extends Exception {}

public class TurnOffChecking {
  private static Test monitor = new Test();
  public static void main(String[] args) {
    WrapCheckedException wce = new WrapCheckedException();
    // You can call f() without a try block, and let
    // RuntimeExceptions go out of the method:
    wce.throwRuntimeException(3);
    // Or you can choose to catch exceptions:
    for(int i = 0; i < 4; i++)
      try {
        if(i < 3)
          wce.throwRuntimeException(i);
        else
          throw new SomeOtherException();
      } catch(SomeOtherException e) {
          System.out.println("SomeOtherException: " + e);
      } catch(RuntimeException re) {
        try {
          throw re.getCause();
        } catch(FileNotFoundException e) {
          System.out.println(
            "FileNotFoundException: " + e);
        } catch(IOException e) {
          System.out.println("IOException: " + e);
        } catch(Throwable e) {
          System.out.println("Throwable: " + e);
        }
      }
    monitor.expect(new String[] {
      "FileNotFoundException: " +
      "java.io.FileNotFoundException",
      "IOException: java.io.IOException",
      "Throwable: java.lang.RuntimeException: Where am I?",
      "SomeOtherException: SomeOtherException"
    });
  }
} ///:~
1
ответ дан 29 November 2019 в 22:31
поделиться

У меня возникла та же проблема.

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

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

Подход, который я выбрал, состоит в создании списка действий «отката». Если рабочий процесс завершается успешно, они игнорируются. Если возникает исключение, я выполняю откаты и представляю пользователю исключение.

Это:

  • сохраняет целостность данных
  • позволяет намного проще кодировать

Типичная функция выглядит так:

returntype func(blah-blah-blah, Transaction tr)
{
    // IO example
    Stream s = null;
    try
    {
        s = new FileStream(filename);
        tr.AddRollback(File.Delete(filename));
    }
    finally
    {
        if (s != null)
            s.close();
    }
}

Типичное использование: :

Transaction tr = new Transaction();
try
{
    DoAction1(blah1, tr);
    DoAction2(blah2, tr);
    //...
}
catch (Exception ex)
{
    tr.ExecuteRollbacks();
    // queue the exception message to the user along with a command to repeat all the actions above
}

Это немного немного сложнее в реальном мире,

1
ответ дан 29 November 2019 в 22:31
поделиться

Обычным шаблоном для работы с этим является цепочка исключений . Вы просто оборачиваете FileNotFoundException в RuntimeException:

catch(FileNotFoundException e) {
    throw new RuntimeException(e);
}

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

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

catch(FileNotFoundException e) {
    throw new RuntimeException(e.getMessage());
}

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

Другое редактирование: Как правильно указывает Торбьёрн Равн Андерсен в своем ответе, не повредит указать, почему вы связываете исключение в цепочку. в комментарии или, что еще лучше, Я бы сказал, просто повторно вызовите IOException везде, где классы JDK / java.io , которые вы используете, вынуждают вас сделать это.

Также я ненавижу классы, которые генерируют исключения из своего конструктора - на вашем месте я бы избавился от них.

1
ответ дан 29 November 2019 в 22:31
поделиться

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

try {
  ....

} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
}
8
ответ дан 29 November 2019 в 22:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: