我刚刚开始重新使用Java,但从未有机会使用try-with-resources
。从表面上看它看起来很棒,因为它可以减少代码,但是在幕后它是否比传统的try-catch
或多或少昂贵的操作?我知道try-catch
已经是一项昂贵的操作,因此我的好奇心。
我给这两种类型做了一个简单的测试,并没有发现任何差异:
long startTime = System.currentTimeMillis();
ArrayList<String> list = null;
try (Scanner sc = new Scanner(new File("file.txt"))) {
list = new ArrayList();
while (sc.hasNext()) {
list.add(sc.next());
}
} catch (Exception ex) {
System.err.println("Error: " + ex.getMessage());
} finally {
long endTime = System.currentTimeMillis();
System.out.println("The program completed in " + (endTime - startTime) + " ms");
}
long startTime = System.currentTimeMillis();
ArrayList<String> list = null;
Scanner sc = null;
try {
sc = new Scanner(new File("file.txt"));
list = new ArrayList();
while (sc.hasNext()) {
list.add(sc.next());
}
} catch (Exception ex) {
System.err.println("Error: " + ex.getMessage());
} finally {
sc.close();
long endTime = System.currentTimeMillis();
System.out.println("The program completed in " + (endTime - startTime) + " ms");
}
两者都产生了15-16ms的时间 - 完全没有明显的差异。但诚然,这是一个非常小的测试例子。
我的问题:引擎盖try-with-resources
比传统try-catch
更贵或更便宜?
答案 0 :(得分:33)
答案 1 :(得分:10)
它的苹果和橘子。 ARM(自动资源管理或try-with-resources)块比您显示的旧式try-catch-finally块更有用。这是因为它生成的代码用于处理suppression mechanism.资源封闭中引发的异常(A related answer详细讨论了这一点。)
如果要编写新代码,请使用ARM块。它更易于阅读,维护,而且功能更多。除非您在严格受限的环境(如智能卡)中运行,否则这些优势可能会超过一些额外字节代码的成本。
答案 2 :(得分:4)
Try-catch-finally和try-with-resources具有基本相同的性能,因为它们在封面下生成基本相同的字节码。
然而,你的第二个版本(try..catch..finally)并没有完全正确,因为它(理论上)可能会在调用NullPointerException
时导致不受欢迎的sc.close()
。如果构建Scanner
的行为导致异常被抛出,则sc
将不会被分配,并且将为null
。
您应该在try..finally
之外构建扫描仪并更改此内容:
Scanner sc = null;
try {
sc = new Scanner(new File("file.txt"));
...
为:
Scanner sc = new Scanner(new File("file.txt"));
try {
...
或者,您应该在调用sc != null
之前检查finally
子句中的sc.close()
。如果您在try..finally之外创建扫描仪,则不需要这样做,所以我建议您这样做。
要执行与try-with-resources相同的工作,您还需要在try..catch
周围放置第二个sc.close()
并使用空的catch块,以忽略在关闭期间抛出的任何异常。如果你这样做,我想你不必太担心空检查。
答案 3 :(得分:0)
传统的try-catch:在try块中,您的代码可能有一个异常,该异常将被抛出,然后被catch块捕获。然后catch块将处理异常。而且,如果您在try
之前打开源文件(例如文件或其他东西),并且需要在finally
中将其关闭,那么close()
可能也会在finally
中执行引发异常,它将替换try
中引发的异常。这种情况通过SE 7之前的嵌套try-catch像这样
try
{
try
{
code with exception;
}
finally
{
close();
}
}
catch(Exception e)
{
Deal the exception
}
这确实很复杂,因此在SE 7之后,当您完成try
块时,我们将使用try-with-resource解决此问题,try(Here)
中的资源将全部关闭。
参考“ Core Java”版本:基于SE 7的9