尝试使用资源与Try-Catch

问题描述 投票:26回答:4

我一直在看代码,我已经看过尝试资源。之前我使用过标准的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");
}
java try-catch try-with-resources
4个回答
43
投票

try-with-resources的要点是确保资源被关闭,而不需要应用程序代码。

当您不使用try-with-resources时,可能存在一个称为异常屏蔽的陷阱。当try块中的代码抛出异常,并且finally中的close方法也抛出异常时,try块抛出的异常会丢失,并且finally中抛出的异常会被传播。这通常是不幸的,因为关闭时抛出的异常是无用的,而有用的异常是信息性异常。

这种异常屏蔽是一个令人讨厌的问题,可以防止资源尝试发生。

作为确保异常屏蔽不会丢失重要异常信息的一部分,当开发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块中的异常将掩盖另一个异常。但是开发人员可以选择捕获关闭时抛出的异常,而不是传播它。


5
投票

你错过了什么,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();
}

1
投票

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


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块才会被执行。

© www.soinside.com 2019 - 2024. All rights reserved.