正确使用Java异常

时间:2011-11-08 10:09:59

标签: java exception exception-handling

我有几个关于在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()方法以查看它是否可行,然后失败并提醒用户。 / p>

我的问题:

  1. 我在doHttpGetRequest()中打开一个InputStream,该方法抛出IOException。如果它抛出异常,我如何关闭InputStream?如果没有允许我关闭资源的方法中的finally块,我很困惑。

  2. 在main()中,我只对getPhoto()是否有效感兴趣。我是否更好地使用try / catch块在getPhoto()中包围语句并捕获JSONException,在捕获时抛出新的IOException?这将导致只需要在main()中捕获一种异常,从而导致更简单的代码并且没有重复的功能。

  3. 如果p.getPhoto()抛出异常,我想重新尝试它(可能两次)然后在失败时显示用户警报。这样做是否有共同的编程结构?

3 个答案:

答案 0 :(得分:1)

  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;
    
  4. 编辑:修正错误

答案 1 :(得分:0)

  1. 您可以捕获异常,清理并重新抛出异常。为什么要避免使用finally阻止?它看起来很适合那里。

  2. 分别处理这两个例外的代码可能更多。

  3. 将其置于for循环中,continue如果有异常,break如果没有。

答案 2 :(得分:0)

  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);