说我有以下代码:
try {
Reader reader = new FileReader("/my/file/location");
//Read the file and do stuff
} catch(IOException e) {
e.printStackTrace();
} finally {
reader.close();
}
为什么读者只存在于try
括号的范围内?这是为了阻止先前在对象Exception
尚未初始化或设置的代码中抛出reader
吗?
我应该如何清理try
条款中存在的对象,还是必须将它们带到外面?
答案 0 :(得分:4)
您必须将它们带到外面,否则变量仅存在于try块中。但这是一种改进。如果您将代码更改为:
Reader reader = new FileReader("/my/file/location");
try {
//Read the file and do stuff
} catch(IOException e) {
e.printStackTrace();
} finally {
reader.close();
}
然后try-block中的代码,包括finally,都可以依赖于已经成功创建的阅读器。否则,在您的示例中,如果实例化失败,您的代码仍然会在出路时尝试关闭读取器,该读取器仍为空。
在这个更改的示例中,catch块的实例化引发的异常不会被catch块处理。
问题的组合使你在这里,一个是你更担心尝试用一个catch块来压缩所有异常,而不是在开始调用它之前确保读者处于有效状态。 (你会在JDBC代码中看到这一个 - try-block-to-rule-them-all风格,人们根本无法忍受编写所有嵌套的try块,它太难以容忍了。)另外,它是非常玩具示例,以便像这样在本地捕获所有异常,在现实生活中如果出现问题你想要抛出异常,以便应用程序的其余部分可以知道出错了,给你类似的东西
public void doStuffWithFile() throws IOException {
Reader reader = new FileReader("/my/file/location");
try {
//Read the file and do stuff
} finally {
try {
reader.close();
} catch (IOException e) {
// handle the exception so it doesn't mask
// anything thrown within the try-block
log.warn("file close failed", e);
}
}
}
这与try-with-resources非常相似。 try-with-resources首先创建对象,然后执行try块,然后关闭它创建的东西,确保关闭时抛出的任何异常都不会掩盖try-block中抛出的异常。创建对象仍然有可能抛出异常,它不会被try-with-resources处理。
public void doStuffWithFile() throws IOException {
try (Reader reader = new FileReader("/my/file/location")) {
//Read the file and do stuff
}
}