2

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

1) 一些变量需要在 try 括号内声明,否则它们将不在范围内
2) 最终,即使我的 return 语句最终也必须在 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;
    }
4

8 回答 8

10

如果异常处理不需要在方法中发生,还有一个选择——在getContents方法中添加一个throws子句以使方法抛出异常:

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

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

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

编辑

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

在这种情况下,该getContents方法似乎获取了指定 的内容File,并将 a 返回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返回给方法调用者可能会更好,因此可以在可以采取适当的替代操作的地方执行异常处理地方。

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

于 2009-06-15T04:45:46.850 回答
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,这在性能方面要好得多。

于 2009-06-15T04:50:42.000 回答
4
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之外;否则,可以在块内声明引用。tryfinallyreadertry

而且我没有处理异常,我认为这与您的问题无关。

于 2009-06-15T05:35:28.650 回答
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);
    }
}
于 2009-06-15T20:51:56.237 回答
1

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

于 2009-06-15T04:46:59.203 回答
1

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

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

因此,如果我使用 null 返回值来指示错误,我会这样做

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;
}
于 2009-06-15T04:49:15.420 回答
0

IMHO you have two ways to deal properly with the exceptions (here, IOException and FileNotFoundException) :

  • you simply throw it, so the caller must deal with it, but in counterpart have the detailed reason of the failure and so can choose the most appropriate behavior
  • you embed both possible exceptions in only one of yours, that express "something went wrong" so the caller have only one exception to deal with (but the end user message will probably be less acute)

To have good advice about exceptions, see also : Why do Java people frequently consume exceptions silently?

于 2009-06-15T20:36:26.650 回答
0

从 Java 7 开始,您可以使用try-with-resources来确保您的资源正确且“自动”关闭。您所需要的只是一个实现了java.lang.AutoCloseable它的对象BufferedReader。文档中实际上有以下示例:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}
于 2015-09-30T08:05:47.810 回答