我经常看到这种资源清理方式:
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} finally {
if (in != null) {
in.close();
}
}
我一直使用以下风格:
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
但我错过了什么吗?我没有看到前者的优势吗?
答案 0 :(得分:1)
我怀疑它避免使用两个嵌套的try / catch块而不是一个。
InputStream in = null;
try {
in = new FileInputStream(file);
// ...
} catch(IOException ioe) {
// handle exception.
} finally {
IOUtils.closeQuietly(in);
}
第二种情况不完整。
try {
final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
} catch(IOException e) {
// handle exception
}
如果您有多个文件,这可能会非常混乱。
答案 1 :(得分:0)
假设在第一个示例中,在定义 in 之前,您还有一些其他代码可以让您退出try块。如果你在没有定义的情况下进入finally,那么在尝试关闭它时会得到NullPointerException。所以你必须进行检查以避免这样的错误。
答案 2 :(得分:0)
此处null
的{{1}}检查是必要的,因为可能无法分配变量。在这种情况下,在调用时尝试关闭它时会抛出NullPointerException:
InputStream
在try / catch块的第二个块 outside 中:
in.close();
在进入区块之前,您可以轻松地遇到其他例外,final InputStream in = new FileInputStream(file);
try {
// ...
} finally {
in.close();
}
永远不会关闭。
答案 3 :(得分:0)
第二个不会编译,因为FileInputStream
的构造函数可以抛出FileNotFoundException
,因此你需要一个额外的try-catch
块,除非当然方法本身抛出它
另一个常见的习惯是编写closeQuietly()
方法,以避免在if (is != null)
块上编写finally
检查。这就是Apache Common的IOUtils
所做的:
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
}
} catch (IOException ioe) {
// ignore
}
}
另请注意自 Java 7以来,您可以使用以下内容:
try (InputStream is = new FileInputStream(file)) {
} catch (final FileNotFoundException | IOException ex) {
}
答案 4 :(得分:0)
这是一个非常简单的示例,并且在您在同一个bloke中创建InputStream
时可能不会产生问题。但是如果由于某些InputStream
其他错误导致Exception or
关闭,那么您的代码将失败,因此最好检查InputStream
是否可用
答案 5 :(得分:0)
让我们说你需要打开一个而不是两个文件。你会做的
final InputStream in = new FileInputStream(file1);
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
in.close();
}
如果out
无法打开,您将收到异常,因为try
阻止in
阻止finally
阻止InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
if (out != null) out.close();
if (in != null) in.close();
}
阻止。
在另一种方法中:
out
如果finally
无法打开,您将转到in
块并关闭两个流。如果in
无法打开,您将转到finally块,并且仅免费out==null
- 因为close()
。
修改强>
正如所提到的aetheria,该代码不起作用,因为try
在Java中抛出异常。可以通过将每个资源版本放入其自己的catch
- InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(file1);
out = new FileOutputStream(file2);
// ...
} finally {
try{ out.close(); }catch(Exception e){}
try{ in.close(); }catch(Exception e){}
}
块中来轻松修复:
in
我放弃了空检查 - 如果out
或NullPointerException
为空,则会抛出一个将被忽略的close
。我忽略finally
例外的原因是处理方法不应该首先抛出异常。如果需要处理结束例外,您可以再次关闭流, close
块之后。这样,可以关闭的任何流都将被关闭(因此您不必担心它),并且您可以更优雅地处理来自try
的任何异常。
现在,aetheria还建议为每个资源添加一个单独的finally
- final InputStream in = new FileInputStream(file1);
try {
final OutputStream out = new FileOutputStream(file2);
try {
// ...
} finally {
out.close();
}
} finally {
in.close();
}
块,如下所示:
{{1}}
这很有效,但即使只有两个资源,它也不那么优雅,因为它会分配分配并释放代码,这使得跟踪它变得更加困难(至少在我看来)。