Try With Resources vs Try-Catch

2019-01-04 10:56发布

I have been looking at code and I have seen try with resources. I have used the standard try-catch statement before and it looks like they do the same thing. So my question is Try With Resources vs Try-Catch what are the differences between those, and which is better.

Here is a try with resources :

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条回答
地球回转人心会变
2楼-- · 2019-01-04 11:09

The main point of try-with-resources is to make sure resources are closed, without requiring the application code to do it. There are some finer points to consider, though.

When you don't use try-with-resources there's a potential pitfall called exception-masking. When code in a try block throws an exception, and the close method in the finally also throws an exception, the exception thrown by the try block gets lost and the exception thrown in the finally gets propagated. This is usually unfortunate, since the exception thrown on close is something unhelpful while the useful exception is the informative one. Using try-with-resources to close your resources will prevent any exception-masking from taking place.

As part of making sure exception-masking wouldn't lose important exception information, when try-with-resources was developed they had to decide what to do with the exceptions thrown from the close method.

With try-with-resources, if the try block throws an exception and the close method also throws an exception, then the exception from the close block gets tacked on to the original exception:

... there are situations where two independent exceptions can be thrown in sibling code blocks, in particular in the try block of a try-with-resources statement and the compiler-generated finally block which closes the resource. In these situations, only one of the thrown exceptions can be propagated. In the try-with-resources statement, when there are two such exceptions, the exception originating from the try block is propagated and the exception from the finally block is added to the list of exceptions suppressed by the exception from the try block. As an exception unwinds the stack, it can accumulate multiple suppressed exceptions.

On the other hand if your code completes normally but the resource you're using throws an exception on close, that exception (which would get suppressed if the code in the try block threw anything) gets thrown. That means that if you have some JDBC code where a ResultSet or PreparedStatement is closed by try-with-resources, an exception resulting from some infrastructure glitch when a JDBC object gets closed can be thrown and can rollback an operation that otherwise would have completed successfully.

Without try-with-resources whether the close method exception gets thrown is up to the application code. If it gets thrown in a finally block when the try block throws an exception, the exception from the finally block will mask the other exception. But the developer has the option of catching the exception thrown on close and not propagating it.

查看更多
一夜七次
3楼-- · 2019-01-04 11:19

Any object (either the class or their superclass) that implements java.lang.AutoCloseable or java.io.Closeable can only be used in try-with-resource clause. AutoClosable interface is the parent interface and Closable interface extends the AutoClosable interface.AutoClosable interface has method close which throws Exception while Closable interface has method that throws IOException. We can also have catch and finally block followed by try-with-resource like ordinary try, catch and finally, but catch and finally block only get executed once the resource declared inside the try-with-resource clause is closed.

查看更多
闹够了就滚
4楼-- · 2019-01-04 11:21

You missed something, the finally block. The try-with-resouces will make it something like,

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) {
    } 
  }
}

Which means you really wanted something like (never swallow exceptions),

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();
}
查看更多
走好不送
5楼-- · 2019-01-04 11:27

The only difference is that try-resource is adding automatically resource.close(); as you would do in finally block

查看更多
登录 后发表回答