Java异常的正确使用

Java异常的正确使用,java,exception,exception-handling,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 =

关于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()方法几次,看看它是否有效,然后失败并警告用户

我的问题是:

  • 我正在doHttpGetRequest()中打开一个InputStream,该方法正在抛出一个IOException。如果InputStream引发异常,如何关闭它?如果方法中没有允许我关闭资源的finally块,我会感到困惑

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

  • 如果p.getPhoto()抛出异常,我想重新尝试(可能两次),然后在失败时显示用户警报。是否有一个通用的编程结构来执行此操作

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

  • 这可能比单独处理这两个异常更需要代码

  • 将其放入
    for
    循环中,如果出现异常,则继续
    ;如果没有异常,则中断

  • doHttpGetRequest()
    应该负责关闭输入流。最后一个区块适合关闭(你为什么不想要最后一个区块?)

  • 是否必须向main方法传递任何异常。您可以用
    try{}
    包围
    doHttpGetRequest(url)
    ,用另一个包围
    processJson
    (我想这一个不会从重试中受益)。这将使
    main()
    方法更干净

  • 如果你同意我的建议的话。您可以这样进行重试:

    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;
    
    InputStream is;
    try {
        is = openStream(); //This is a sample code, which 
        //Do something with the stream
    } finally {
        if (is != null) is.close();
    }
    
    String响应=null;
    对于(int i=0;i
  • 编辑:错误修正

  • 您仍然应该使用try finally块,以便能够关闭资源。块的使用方式如下:

    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;
    
    InputStream is;
    try {
        is = openStream(); //This is a sample code, which 
        //Do something with the stream
    } finally {
        if (is != null) is.close();
    }
    
    这样,如果抛出异常,流将被关闭,异常将在别处处理

  • 我建议您创建自己的异常(比如PhotoradingException)并从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);
    
    Photo p=null;
    异常ex=null;
    for(int trys=0;trys

  • 如果这是Android应用程序的代码,为什么会有
    main
    方法?或者,您为桌面编写代码是为了以后将其移植到Android?这是一段简单的演示代码,用于回答问题。设置异常原因的传统方法是将原因异常向上传递到构造函数链。@Stephen C如果您从
    java.lang.Exception
    。但是,例如,
    IOException
    ,在Java1.5中没有这样的构造函数<但是,code>initCause
    仍然可用。因为OP提到了为Android编写应用程序,而Android 2.3之前的版本是基于Java1.5库的,所以我决定提出一种始终有效的方法。