#java #exception #exception-handling
#java #исключение
Вопрос:
У меня есть несколько вопросов о наилучшем использовании исключений в Java.
Рассмотрим приведенный ниже код:
private String doHttpGetRequest(String url) throws IOException {
...
}
private Photo processJson(String json) throws JSON Exception{
...
}
private Photo getPhoto() throws IOException, JSON Exception {
String url = "http://...";
String response = doHttpGetRequest(url);
Photo photo = processJson(response);
photo.downloadImage();
return photo;
}
public static void main(String args[]) {
Photo p = null;
try {
p = getPhoto();
} catch( JSONException j ) {
// Re-try a few times, then display user alert
} catch( IOException e ) {
// Re-try a few times, then display user alert
}
if( p!=null)
// now display photo
}
Этот код предназначен для приложения Android, где соединение может быть не очень надежным, поэтому я хотел бы несколько раз повторить метод getPhoto (), чтобы посмотреть, сработает ли он, затем сбой и оповещение пользователя.
Мои вопросы:
-
Я открываю InputStream в doHttpGetRequest(), и этот метод выдает исключение IOException. Как мне закрыть InputStream, если он вызвал исключение? Без блока finally в методе, который позволил бы мне закрыть ресурсы, я в замешательстве.
-
В main () меня интересует только то, работает getPhoto () или нет. Было бы лучше окружить инструкции внутри getPhoto () блоком try / catch и перехватить исключение JSONException, создавая новое исключение IOException при его обнаружении? Это привело бы к необходимости перехватывать только один тип исключения в main(), что привело бы к упрощению кода и отсутствию дублирующей функциональности.
-
Если p.getPhoto() выдает исключение, я хочу повторить попытку (возможно, дважды), а затем отобразить предупреждение пользователя, если это не удается. Существует ли общая структура программирования для этого?
Комментарии:
1. Если это код для приложения Android, то почему существует
main
метод? Или вы пишете свой код для рабочего стола с намерением позже перенести его на Android?2. Этот код является просто демонстрационным кодом для целей вопроса.
Ответ №1:
-
doHttpGetRequest()
должен отвечать за закрытие inputstream. Finally-блок там был бы пригоден для закрытия (почему вы не хотите блокировать finally?). -
Нужно ли передавать какие-либо исключения в метод main. Вы могли бы окружать
doHttpGetRequest(url)
с помощьюtry{}
и окружатьprocessJson
другим (я полагаю, что этот не выигрывает от повторных попыток). Это сделало быmain()
метод более чистым. -
Если вы согласитесь с моим предложением на 2. вы могли бы повторить попытку следующим образом:
String response = null; for (int i = 0; i < RETRY_COUNT amp;amp; response == null; i ){ try { response = doHttpGetRequest(url); } catch (IOException e){ // Possibly log the error here } } if (response == null) return null;
РЕДАКТИРОВАТЬ: Исправлена ошибка
Ответ №2:
-
Вы можете перехватить исключение, очистить и повторно создать его. Почему вы избегаете использования
finally
block? Похоже, что это очень хорошо бы туда вписалось. -
Вероятно, потребуется больше кода, чем для обработки этих двух исключений по отдельности.
-
Поместите это в
for
цикл,continue
если было исключение иbreak
если нет.
Ответ №3:
-
Вам все равно следует использовать блокировку try-finally, чтобы вы могли закрыть ресурсы. Блок используется следующим образом:
InputStream is; try { is = openStream(); //This is a sample code, which //Do something with the stream } finally { if (is != null) is.close(); }
Таким образом, если генерируется исключение, поток в любом случае будет закрыт, и исключение будет обработано в другом месте.
-
Я предлагаю вам создать свое собственное исключение (скажем, PhotoReadingException) и запустить его из getPhoto(), но установить его причину в исходное исключение с помощью
initCause(Throwable cause)
метода. -
Конечно, вы можете использовать цикл и переменную, которая показывает, была ли операция успешной.
Photo p = null; Exception ex = null; for (int tries = 0; tries < MAX_TRIES; tries ) { try { p = getPhoto(); break; } catch (PhotoReadingException photoException) { ex = photoException; } } if (ex != null) reportException(ex);
Комментарии:
1. Обычным способом установления причины исключения является передача исключения cause вверх по цепочке конструкторов.
2. @Stephen C Это возможно, если вы выводите свое исключение из
java.lang.Exception
. Однако,IOException
например, в Java 1.5 нет такого конструктора.initCause
однако он все еще доступен. Поскольку в OP упоминалось о написании приложения для Android, а Android до версии 2.3 основан на библиотеках Java 1.5, я решил упомянуть способ, который всегда работает.