Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(When) Should try-with enclose the AutoCloseable constructor?

Tags:

java

try-catch

The Oracle Java documentation for the then-new try-with-resources shows all examples with the AutoCloseable in question being constructed in the try(...):

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    ...
}

That seems secure in the sense that even if the constructor (as opposed to some subsequent event) already acquires resources that have to be released, they would be released if we ran into an exception.

However, as, e.g., https://www.baeldung.com/java-try-with-resources points out, starting with Java 9, we can use effectively final resources initialized before the try(...):

FileOutputStream fos = new FileOutputStream("output.txt");
try (fos) { 
    // do stuff
}

In a similar, pre-Java-9 vein, I have seen:

CustomStreamLikeThing connection = new CustomStreamLikeThing("db_like_thing");
// ... do some stuff that may throw a RuntimeException
try (CustomStreamLikeThing connection2=connection) { 
    // do some more stuff
}

Which seems legal, but at the same time to somewhat weaken the concept: If the CustomStreamLikeThing acquires closeable resources, they may not be released.

Are there guidelines about when the constructor of an AutoCloseable should be enclosed in the try(...), or is this a matter of taste (as in "enclose all those things that I think could throw an exception")?

like image 889
Hans Avatar asked Nov 02 '25 08:11

Hans


1 Answers

You should always use try-with-resources if you can.

When you allocate a resource, you should make sure the resource is always released when you're done with it. That "always" generally means that you should use a try-finally, so that any error occurring after the resource is allocate won't prevent the resource from being released.

Which means that if you don't use try-with-resources, you need to use try-finally, so why did I say to always use try-with-resources?

Because calling close() can fail too, and try-with-resources handles that for you, with a feature added when try-with-resources was added, called suppressed exceptions.

You'll know the importance of this if you've ever cursed at a stacktrace of a failed close() call, that has replaced the exception thrown by the code that should have been in a try-with-resources block, so you now don't know what actually caused the problem.

Suppressed exceptions is a commonly overlooked feature, but is a great time saver when a cascaded exception is thrown by a close method. For that alone, always use try-with-resources.

Side benefit: Try-with-resources is less code than using try-finally, and you should definitely use one of those two when handling resources.

like image 185
Andreas Avatar answered Nov 03 '25 23:11

Andreas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!