47

我一直在查看代码,并且已经看到尝试使用资源。我以前使用过标准的 try-catch 语句,看起来他们做同样的事情。所以我的问题是Try With Resources vs Try-Catch 它们之间有什么区别,哪个更好。

这是资源的尝试:

objects jar = new objects("brand");
objects can= new objects("brand");

try (FileOutputStream outStream = new FileOutputStream("people.bin")){
    ObjectOutputStream stream = new ObjectOutputStream(outStream);

    stream.writeObject(jar);
    stream.writeObject(can);

    stream.close();
} catch(FileNotFoundException e) {
    System.out.println("sorry it didn't work out");
} catch(IOException f) {
    System.out.println("sorry it didn't work out");
}
4

5 回答 5

67

try-with-resources 的主要目的是确保资源可靠关闭而不会丢失信息。

当您不使用 try-with-resources 时,存在一个称为异常屏蔽的潜在陷阱。当 try 块中的代码抛出异常,而 finally 中的 close 方法也抛出异常时,try 块中抛出的异常会丢失,而 finally 中抛出的异常会被传播。这通常是不幸的,因为关闭时抛出的异常是无用的,而有用的异常是提供信息的异常。(因此,您不会看到告诉您违反了哪个参照完整性约束的 SQLException,而是会显示诸如 BrokenPipeException 之类的内容,其中关闭资源失败。)

这种异常屏蔽是一个恼人的问题,try-with-resources 可以防止发生。

作为确保异常屏蔽不会丢失重要异常信息的一部分,当 try-with-resources 被开发时,他们必须决定如何处理从 close 方法抛出的异常。

使用 try-with-resources,如果 try 块抛出异常并且 close 方法也抛出异常,则close 块中的异常会附加到原始异常

...在某些情况下,可以在同级代码块中引发两个独立的异常,特别是在 try-with-resources 语句的 try 块和关闭资源的编译器生成的 finally 块中。在这些情况下,只能传播引发的异常之一。在 try-with-resources 语句中,当有两个这样的异常时,将传播源自 try 块的异常,并将 finally 块的异常添加到由 try 块的异常抑制的异常列表中。当一个异常展开堆栈时,它可以累积多个被抑制的异常。

另一方面,如果您的代码正常完成,但您使用的资源在关闭时抛出异常,则该异常(如果 try 块中的代码抛出任何东西,该异常将被抑制)将被抛出。这意味着,如果您有一些 JDBC 代码,其中 ResultSet 或 PreparedStatement 由 try-with-resources 关闭,则当 JDBC 对象关闭时,可能会抛出由某些基础设施故障导致的异常,并且可以回滚本来可以成功完成的操作.

如果没有 try-with-resources,是否抛出 close 方法异常取决于应用程序代码。如果 try 块抛出异常时它被抛出到 finally 块中,则 finally 块中的异常将掩盖另一个异常。但是开发人员可以选择捕获关闭时抛出的异常而不传播它。

于 2014-10-22T20:15:21.840 回答
6

你错过了一些东西,finally街区。会try-with-resouces让它像,

FileOutputStream outStream = null;
try {
  outStream = new FileOutputStream("people.bin");
  ObjectOutputStream stream = new ObjectOutputStream(outStream);

  stream.writeObject(jar);
  stream.writeObject(can);

  stream.close();
} catch(FileNotFoundException e) {
    System.out.println("sorry it didn't work out");
} catch(IOException f) {
    System.out.println("sorry it didn't work out");
} finally {
  if (outStream != null) { 
    try { 
      outStream.close(); 
    } catch (Exception e) {
    } 
  }
}

这意味着你真的想要类似的东西(永远不要吞下例外),

try (FileOutputStream outStream = new FileOutputStream("people.bin");
     ObjectOutputStream stream = new ObjectOutputStream(outStream);) {
  stream.writeObject(jar);
  stream.writeObject(can);
  // stream.close(); // <-- closed by try-with-resources.
} catch(FileNotFoundException e) {
    System.out.println("sorry it didn't work out");
    e.printStackTrace();
} catch(IOException f) {
    System.out.println("sorry it didn't work out");
    e.printStackTrace();
}
于 2014-10-22T20:01:48.177 回答
4

唯一的区别是 try-resource 会自动添加resource.close(); ,就像您在finally块中所做的那样

于 2014-10-22T20:01:05.800 回答
0

实现 java.lang.AutoCloseable 或 java.io.Closeable 的任何对象(类或其超类)只能在 try-with-resource 子句中使用。AutoClosable 接口是父接口,Closable 接口扩展了 AutoClosable 接口。AutoClosable 接口有 close 方法抛出异常,而 Closable 接口有方法抛出 IOException。我们也可以像普通的 try、catch 和 finally 一样在 try-with-resource 之后使用 catch 和 finally 块,但 catch 和 finally 块只有在 try-with-resource 子句中声明的资源关闭时才会执行。

于 2018-01-23T11:22:14.000 回答
-1

简而言之,它是支持 AutoClosable 接口并为您调用 close() 方法以获得任何结果的语法糖。

于 2020-02-27T11:39:01.407 回答