【问题标题】:Try With Resources vs Try-Catch [duplicate]Try With Resources vs Try-Catch [重复]
【发布时间】:2014-12-18 09:48:30
【问题描述】:

我一直在查看代码,并且已经看到尝试使用资源。我以前使用过标准的 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");
}

【问题讨论】:

  • 不同之处在于您不需要在 try-wth-resource 中调用 stream.close()。如果您有一个关闭它的 finally 子句,它会自动调用。在 try-with-resouce 子句中只能使用实现 Closeable 或 AutoCloseable 的对象。
  • 您不需要(或者很可能不应该)在try{..} 部分调用stream.close();。它应该在 finally 部分完成,try-with-resources 将为您处理(顺便说一句,try-with-resources 可以处理多个资源)。

标签: java try-catch try-with-resources


【解决方案1】:

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方法也抛出异常,那么the exception from the close block gets tacked on to the original exception:

... 在某些情况下,可以在同级代码块中引发两个独立的异常,特别是在 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 块中的异常将掩盖另一个异常。但是开发人员可以选择捕获关闭时抛出的异常而不传播它。

【讨论】:

  • 我希望“finally”块有一种简单的方法来找出从“try”中抛出的异常(如果有的话),以便允许进行相同类型的传播清理-exceptions-if-no-others-are-pending logic in user code.
【解决方案2】:

你错过了一些东西,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();
}

【讨论】:

  • stream.close();在 try 块中是不必要的,因为无论如何流都会在 finally 块中关闭。
  • @Meraman 我在回答的最后部分注意到了这一点。请注意,OP 的问题有 no finally 块。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    实现 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 子句中声明的资源关闭时才会执行。

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多