Обычный шаблон для решения этой проблемы - это цепочка исключений . Вы просто оборачиваете 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);
}
Вы можете преобразовать отмеченное исключение в непроверенное, вложив его в RuntimException. Если исключение обнаружено выше в стеке и выводится с помощью printStackTrace (), также будет отображаться стек для исходного исключения.
try {
// code...
}
catch (IOException e) {
throw new RuntimeException(e);
}
Это хорошее решение, которое вы должны без колебаний использовать в таких ситуациях.
Рассмотрите возможность использования вместо этого формы
throw new RuntimeException("This should never happen", e);
. Это позволяет вам передать смысл сопровождающему, который будет следовать за вами, как при чтении кода, так и ДОЛЖНО, чтобы исключение произошло в каком-то странном сценарии.
РЕДАКТИРОВАТЬ: Это также хороший способ передать исключения через механизм, не ожидая тех исключений. Например, если у вас есть итератор «получить больше строк из базы данных», интерфейс Iterator не позволяет генерировать, например, исключение FileNotFoundException, поэтому вы можете обернуть его таким образом. В коде ИСПОЛЬЗУЯ итератор, вы можете затем перехватить исключение времени выполнения и проверить исходное исключение с помощью getCause (). ОЧЕНЬ полезно при переходе по устаревшим кодовым путям.
Я немного погуглил и нашел этот кусок кода. Мне кажется, это более гибкий подход
Комплименты этой статье
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"
});
}
} ///:~
У меня возникла та же проблема.
В простейшем случае вы сообщаете пользователю об ошибке и предлагаете повторить или отменить операцию.
В общем случае, рабочий процесс - это последовательность действий (включая ввод-вывод), где каждое действие «предполагает», что предыдущее было успешным.
Подход, который я выбрал, состоит в создании списка действий «отката». Если рабочий процесс завершается успешно, они игнорируются. Если возникает исключение, я выполняю откаты и представляю пользователю исключение.
Это:
Типичная функция выглядит так:
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
}
Это немного немного сложнее в реальном мире,
Обычным шаблоном для работы с этим является цепочка исключений . Вы просто оборачиваете FileNotFoundException в RuntimeException:
catch(FileNotFoundException e) {
throw new RuntimeException(e);
}
Этот шаблон применим не только тогда, когда исключение не может возникнуть в конкретной ситуации (например, вашей), но также когда у вас нет средств или намерения действительно обработать исключение (например, сбой связи с базой данных).
Правка : Остерегайтесь этого похожего на вид антишаблона, который я слишком часто видел в дикой природе:
catch(FileNotFoundException e) {
throw new RuntimeException(e.getMessage());
}
Делая это, вы выбрасываете всю важную информацию в исходный stacktrace, который часто затрудняет отслеживание проблем.
Другое редактирование: Как правильно указывает Торбьёрн Равн Андерсен в своем ответе, не повредит указать, почему вы связываете исключение в цепочку. в комментарии или, что еще лучше, Я бы сказал, просто повторно вызовите IOException везде, где классы JDK / java.io
, которые вы используете, вынуждают вас сделать это.
Также я ненавижу классы, которые генерируют исключения из своего конструктора - на вашем месте я бы избавился от них.
Если ваша позиция такова, что это маловероятно и нужно просто завершить программу, используйте существующее исключение времени выполнения, даже Само RuntimeException (если не IllegalStateException).
try {
....
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}