Правильное использование исключений Java - PullRequest
0 голосов
/ 08 ноября 2011

У меня есть несколько вопросов о наилучшем использовании исключений в 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 (), чтобы посмотреть, сработает ли он, а затем завершить работу и предупредить пользователя.

Мои вопросы:

  1. Я открываю InputStream в doHttpGetRequest (), и этот метод вызывает IOException. Как закрыть InputStream, если он выдал исключение? Без блока finally внутри метода, который позволил бы мне закрывать ресурсы, я запутался.

  2. В main () меня интересует только, работает ли getPhoto () или не работает. Не лучше ли окружить операторы внутри getPhoto () блоком try / catch и перехватить JSONException, создавая новое IOException, когда оно перехватывается? Это приведет к тому, что в main () придется отлавливать только один тип исключений, что приведет к более простому коду и отсутствию дублирующих функций.

  3. Если p.getPhoto () выдает исключение, я хочу повторить попытку (возможно, дважды), а затем отобразить предупреждение пользователя, если это не удалось. Есть ли общая структура программирования для этого?

Ответы [ 3 ]

1 голос
/ 08 ноября 2011
  1. doHttpGetRequest() должен отвечать за закрытие входного потока.Наконец-то блок будет подходящим для закрытия (почему вы не хотите, чтобы, наконец, блок?).

  2. Вам нужно передать какие-либо исключения в метод main.Вы можете окружить doHttpGetRequest(url) с помощью try{} и окружить processJson с другим (я надеюсь, что этот не принесет пользы от повторных попыток).Это сделает метод main() более чистым.

  3. Если вы согласитесь с моим предложением о 2., вы можете повторить попытку следующим образом:

    String response = null;
    for (int i = 0; i < RETRY_COUNT && response == null; i++){
      try {
        response = doHttpGetRequest(url);
      } catch (IOException e){
        // Possibly log the error here
      }
    }
    if (response  == null) return null;
    

РЕДАКТИРОВАТЬ: Исправление

0 голосов
/ 08 ноября 2011
  1. Вы все равно должны использовать блок try-finally, чтобы иметь возможность закрыть ресурсы. Блок используется так:

    InputStream is;
    try {
        is = openStream(); //This is a sample code, which 
        //Do something with the stream
    } finally {
        if (is != null) is.close();
    }
    

    Таким образом, если выдается исключение, поток все равно будет закрыт, а исключение будет обработано в другом месте.

  2. Я предлагаю вам создать собственное исключение (скажем, PhotoReadingException) и выбросить его из getPhoto (), но с помощью метода initCause(Throwable cause) установить его причину для исходного исключения.

  3. Конечно, вы можете использовать цикл и переменную, которая показывает, была ли операция успешной.

    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);
    
0 голосов
/ 08 ноября 2011
  1. Вы можете поймать исключение, очистить и перебросить его. Почему вы избегаете использовать блок finally? Похоже, что он очень хорошо вписался бы туда.

  2. Вероятно, это будет больше кода, чем обработка этих двух исключений по отдельности.

  3. Поместите его в цикл for, continue, если было исключение, и break, если нет.

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