如何最优雅地使用try / catch包围代码

时间:2009-06-15 04:42:10

标签: java exception-handling try-catch

使用try-and-catch时经常遇到一些问题:

1)有些变量需要在try括号内声明,否则它们不在范围内 2)最终,即使我的返回语句最终必须在try括号中,但该方法不会返回任何内容。

解决此类问题的正确方法是什么。

导致此问题的方法示例如下所示。它需要处理一个FileNotFoundException并处理一个IOException。我如何最优雅地做到这一点?

public static String getContents (File file) {
      BufferedReader reader = new BufferedReader(new FileReader(file));
      String contents = new String();
      while (reader.ready())
        contents += reader.readLine();
      return contents;
    }

8 个答案:

答案 0 :(得分:10)

如果在getContents方法中不需要进行异常处理,还有一个选项 - 向方法添加throws子句以使该方法抛出异常:

public static String getContents (File file)
    throws IOException, FileNotFoundException {

这样,调用该方法的代码将处理Exception而不是方法本身。如果try被抛出到调用它的方法,则该方法中不需要catch / Exception块。

这可能是也可能不是处理这种情况的理想方式,具体取决于预期方法的行为方式。

修改

第二个想法,让方法抛出异常可能是一个好主意。我认为D.Shawley的评论我认为总结得很好 - “异常处理应该意味着只处理有意义的异常。”

在这种情况下,getContents方法似乎获取指定File的内容,并向调用者返回String

如果要在getConents方法中执行异常处理,则表明发生错误的唯一方法是将某种预定值(例如null)返回到调用者通知错误发生。

但是,通过让方法本身向调用者返回异常,调用者可以选择做出相应的反应:

try {
    String contents = getContents(new File("input.file"));
} catch (IOException ioe) {
    // Perform exception handling for IOException.
} catch (FileNotFoundException fnfe) {
    // Inform user that file was not found.
    // Perhaps prompt the user for an alternate file name and try again?
}

不是让setContents方法提出自己的协议来通知发生错误,而是将IOExceptionFileNotFoundException抛回方法调用者可能会更好,因此可以在可以进行适当替代操作的地方执行异常处理。

只有在可以进行某些有意义的处理时才应执行异常处理。

答案 1 :(得分:5)

您可以按照以下方式处理:

StringBuilder contents = new StringBuilder();
BufferedReader reader;

try {
   reader = new BufferedReader(new FileReader(file));

   while (reader.ready()) {
      contents.append(reader.readLine());
   }

} catch (FileNotFoundException fne) {
   log.warn("File Not Found", fne);
} catch (IOException ioe) {
   log.warn("IOException", ioe);
} 

return contents.toString();

你可能应该在上面的情况下使用StringBuilder而不是String,但在性能方面要好得多。

答案 2 :(得分:3)

public static String getContents (File file) {
    String contents = new String();
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new FileReader(file));
        while (reader.ready())
            contents += reader.readLine();
    }
    catch (FileNotFoundException ex) {
        // handle FileNotFoundException
    }
    catch (IOException ex) {
        // handle IOException
    }
    finally {
        if (reader != null) {
            try {
                reader.close();
            }
            catch (IOException ex) {
                // handle IOException
            }
        }
    }
    return contents;
}

我添加了finally块来关闭BufferedReader,但您没有在代码中执行此操作。我还建议您使用StringBuilder而不是String连接,但有人已经指出了它。 reader的声明和官方化仅在try块之外,因为我添加了finally块;否则,引用reader可以在try块内声明。

我没有处理例外,我认为这与你的问题无关。

答案 3 :(得分:1)

您可以尝试将return语句移动到finally块中。

答案 4 :(得分:1)

关于变量范围,我不确定是否有更优雅的方法来做到这一点。通常我会尝试在出现错误时考虑返回值,然后将变量赋值给该值。

关于return语句,如果你使用我的上述建议,你可以在try / catch块之后返回。

因此,如果我使用空返回值来指示我将要执行的错误

public static String getContents (File file) {
    String contents = null;
    try {        
        BufferedReader reader = new BufferedReader(new FileReader(file));
        contents = new String();
        while (reader.ready())
            contents += reader.readLine();
    } catch (Exception e) {
        // Error Handling
    }
    return contents;
}

答案 5 :(得分:1)

这里缺少的是一个简单的实用程序,可以大大简化清理工作:

public static void closeAndLog(Closable c) {
    if ( c == null )
        return;

    try { 
        c.close() 
    } catch ( IOException e) {
        LOGGER.warn("Failed closing " + c +, e);
    }
}

这样您的代码就可以成为:

public static String getContents (File file) throws IOException {

    BufferedReader r = null;

    try { 
        r = new BufferedReader(...);
        // do stuff
    } finally {
        closeAndLog(r);
    }
}

答案 6 :(得分:0)

恕我直言,你有两种方法可以正确处理异常(这里是IOException和FileNotFoundException):

  • 你只是抛弃它,所以调用者必须处理它,但在对应方有详细的失败原因,因此可以选择最合适的行为
  • 你只在你的一个中嵌入了两个可能的例外,表示“出了问题”,因此调用者只有一个例外可以处理(但最终用户信息可能不那么尖锐)

要获得有关例外的好建议,另请参阅:Why do Java people frequently consume exceptions silently?

答案 7 :(得分:0)

从Java 7开始,您可以使用try-with-resources来确保资源正确关闭并自动“关闭”。您所需要的只是一个实现var curry = document.getElementsByClassName('active')[0]; $(window).load(function() { curry.style.left = '0px'; }); java.lang.AutoCloseable的对象。实际上文档中有以下示例:

BufferedReader