Try With Resources vs Try-Catch [duplicate]
Asked Answered
H

5

51

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");
}
Hurty answered 22/10, 2014 at 19:58 Comment(2)
the difference is you don't need to call stream.close() in the try-wth-resource. It is called automatically af if you had a finally clause that closes it. Only objects implmenting Closeable or AutoCloseable can be used in try-with-resouce clause.Sewel
You don't need to (or most probably shouldn't) call stream.close(); in try{..} section. It should be done in finally section which try-with-resources will handle for you (BTW try-with-resources can handle multiple resources).Otis
L
77

The main point of try-with-resources is to make sure resources are closed reliably without possibly losing information.

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 informative one is the one thrown from within the try block. (So instead of seeing the SQLException that tells you which referential integrity constraint was violated, you're shown something like BrokenPipeException where closing the resource failed.)

This exception-masking is an annoying problem that try-with-resources prevents from happening.

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.

Liverwurst answered 22/10, 2014 at 20:15 Comment(1)
I wish there were an easy means for "finally" blocks to find out what exception (if any) was thrown from the "try", so as to allow the same sort of propagate-clean-up-exceptions-if-no-others-are-pending logic in user code.Haemostatic
S
9

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();
}
Spleeny answered 22/10, 2014 at 20:1 Comment(2)
stream.close(); in try block is unnecessary, as stream is going to be closed in finally block anyway.Russell
@Meraman I noted that in the last part of my answer. Note that OP's question has no finally block.Spleeny
A
5

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

Asymmetric answered 22/10, 2014 at 20:1 Comment(0)
P
1

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.

Protasis answered 23/1, 2018 at 11:22 Comment(0)
G
1

Succinctly it is syntactic sugar to support the AutoClosable interface and call the close() method for you for any outcome.

Giliana answered 27/2, 2020 at 11:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.