java 如何用 try/catch 最优雅地包围代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/994513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to surround code with try/catch most elegantly
提问by Ankur
I often have some problems when using try-and-catch:
我在使用 try-and-catch 时经常会遇到一些问题:
1) Some variables need to be declared inside the try brackets otherwise they will not be in scope
2) Ultimately even my return statement ends up having to be in the try bracket but then the method doesn't return anything.
1) 一些变量需要在 try 括号内声明,否则它们将不在范围内
2) 最终,即使我的 return 语句最终也必须在 try 括号中,但该方法不返回任何内容。
What is the proper way to get around this sort of problem.
解决此类问题的正确方法是什么。
An example of a method that is causing this issue is the one below. It neesd a FileNotFoundException to be handled and a IOException to be handled. How do I do this most elegantly?
导致此问题的方法示例如下所示。它需要处理 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;
}
回答by coobird
There is one more option if the exception handling doesn't need to happen in the getContentsmethod -- add a throwsclause to the method to make the method throw an exception:
如果异常处理不需要在getContents方法中发生,还有一个选择——在方法中添加一个throws子句,使方法抛出异常:
public static String getContents (File file)
throws IOException, FileNotFoundException {
This way, the code calling the method will handle the Exceptions rather than the method itself. There will be no need for try/catchblocks in that method, if the Exceptions are thrown up to the methods that called it.
这样,调用方法的代码将处理Exceptions 而不是方法本身。如果s 被抛出到调用它的方法,则该方法中不需要try/catch块Exception。
This may or may not be the desired way to handle the situation, depending on how the method is expected to behave.
这可能是也可能不是处理这种情况的理想方式,这取决于该方法的预期行为方式。
Edit
编辑
Upon second thought, making the method throw an exception may be a good idea. I think D.Shawley's comment I think sums it up well -- "exception handling should mean only handling the exception where it makes sense."
再三考虑,让方法抛出异常可能是个好主意。我认为 D.Shawley 的评论总结得很好——“异常处理应该意味着只在有意义的地方处理异常。”
In this case, the getContentsmethod appears to get the contents of a specified File, and returns a Stringto the caller.
在这种情况下,该getContents方法似乎获取指定 的内容File,并将 a 返回String给调用者。
If the exception handling were to be performed in the getConentsmethod, the only way to communicate that an error has occurred is by returning some kind of pre-determined value, such as nullto the caller to inform that an error occurred.
如果要在getConents方法中执行异常处理,则传达发生错误的唯一方法是返回某种预先确定的值,例如null向调用者通知发生了错误。
However, by having the method itself throw an exception back to the caller, the caller can choose to react accordingly:
但是,通过让方法本身向调用者抛出异常,调用者可以选择做出相应的反应:
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?
}
Rather than having the setContentsmethod come up with its own protocol for notifying that an error occurred, it would probably be better to throw the IOExceptionand FileNotFoundExceptionback to the method caller, so the exception handling can be performed at a place where the appropriate alternate actions can take place.
与其让setContents方法提出自己的协议来通知发生了错误,不如抛出IOException并FileNotFoundException返回给方法调用者,这样异常处理可以在可以采取适当替代操作的地方执行地方。
Exception handling should only be performed if some meaningful handling can take place.
只有在可以进行一些有意义的处理时才应执行异常处理。
回答by Jon
You can handle it as follows:
您可以按如下方式处理:
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();
You should probably use a StringBuilder in the case above instead of a String though, much better in terms of performance.
在上述情况下,您可能应该使用 StringBuilder 而不是 String ,但在性能方面要好得多。
回答by cd1
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;
}
I added a finallyblock to close your BufferedReader, although you didn't do it in your code. I'd also suggest you use StringBuilderinstead of Stringconcatenation, but someone has already pointed it out. The declaration and inicialization of readeris outside the tryblock only because of the finallyblock I've added; otherwise, the reference readercould be declared inside the tryblock.
我添加了一个finally块来关闭你的BufferedReader,尽管你没有在你的代码中这样做。我还建议您使用StringBuilder而不是String串联,但有人已经指出了。的声明和初始化reader在try块之外只是因为finally我添加了块;否则,reader可以在try块内声明引用。
and I didn't handle the exceptions, I didn't think that was related to your question.
而且我没有处理异常,我认为这与您的问题无关。
回答by Robert Munteanu
What you're missing here is a simple utility which simplifies cleanup considerably:
您在这里缺少的是一个简单的实用程序,它可以大大简化清理工作:
public static void closeAndLog(Closable c) {
if ( c == null )
return;
try {
c.close()
} catch ( IOException e) {
LOGGER.warn("Failed closing " + c +, e);
}
}
This way your code can become:
这样你的代码就可以变成:
public static String getContents (File file) throws IOException {
BufferedReader r = null;
try {
r = new BufferedReader(...);
// do stuff
} finally {
closeAndLog(r);
}
}
回答by Suvesh Pratapa
You can try to move your return statement into a finallyblock.
您可以尝试将 return 语句移动到finally块中。
回答by Brandon Bodnar
Regarding the variable scope, I not sure if there is a more elegant way to do it. Normally I try to think of what my return value is in case of an error, and then assign the variable to that value.
关于变量范围,我不确定是否有更优雅的方法来做到这一点。通常我会尝试考虑在出现错误时我的返回值是什么,然后将变量分配给该值。
In regards to the return statement, if you use my above suggestion then, you can just return after the try / catch block.
关于 return 语句,如果你使用我上面的建议,你可以在 try / catch 块之后返回。
So if I used a null return value to indicate an error I would do
因此,如果我使用 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;
}
回答by Michael Zilbermann
IMHO you have two ways to deal properly with the exceptions (here, IOException and FileNotFoundException) :
恕我直言,您有两种方法可以正确处理异常(此处为 IOException 和 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?
要获得有关异常的好建议,另请参阅:为什么 Java 人经常默默地使用异常?
回答by Rodrigue
Since Java 7, you can use try-with-resourcesto make sure your resources are closed properly and 'automatically'. All you need is an object that implements java.lang.AutoCloseablewhich BufferedReaderdoes. There is actually the following example in the docs:
从 Java 7 开始,您可以使用try-with-resources来确保您的资源正确且“自动”关闭。你所需要的只是一个实现java.lang.AutoCloseable它的对象BufferedReader。文档中实际上有以下示例:
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}

