Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it good practice to try-with-resource a file writer

I saw this example on the web and in the Book "Effective Java" (by Joshua Bloch).

try(BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))){
  writer.write(str); // do something with the file we've opened
}
catch(IOException e){
  // handle the exception
}

There is no problem with this example, BufferedWriter which will automatically get closed and that, in turn, will close the FileWriter; however, in other case, if we declare 2 nested resources this way:

try (AutoClosable res = new Impl2(new Impl1())) {... }

I guess it might happen that new Impl1() performs fine, but new Impl2() crashes, and in this case Java would have no reference to the Impl1, in order to close it.

Shouldn't it be a better practice to always declare multiple resources independently (even if not required in this case), like this?

try(FileWriter fw = new FileWriter(fileName); 
    BufferedWriter writer = new BufferedWriter(fw)){ ... }
like image 905
Rolintocour Avatar asked Aug 18 '20 08:08

Rolintocour


People also ask

Should be managed by try with resource?

The try -with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try -with-resources statement ensures that each resource is closed at the end of the statement.

How do you write to try with resources?

A resource is an object to be closed at the end of the program. As seen from the above syntax, we declare the try-with-resources statement by, declaring and instantiating the resource within the try clause. specifying and handling all exceptions that might be thrown while closing the resource.

Which of the following is a correct statement about try with resources statement in Java 9?

The try-with-resources statement is a try statement with one or more resources duly declared. Here resource is an object which should be closed once it is no more required. The try-with-resources statement ensures that each resource is closed after the requirement finishes.

Does try with resources flush?

The resources are automatically closed when using try-with-resource block. As part of this process it will also invoke flush automatically.


1 Answers

After some searching I was able to find this article: https://dzone.com/articles/carefully-specify-multiple-resources-in-single-try

By definition JLS 14.20.3 a ResourceList consists of Resources separated by ;. Based on that we can conclude that a nested initialization like AutoClosable res = new Impl2(new Impl1()) is a single resource. Because of that rules defined for try-with-resources with multiple resources won't apply here, important ones being:

Resources are initialized in left-to-right order. If a resource fails to initialize (that is, its initializer expression throws an exception), then all resources initialized so far by the try-with-resources statement are closed. If all resources initialize successfully, the try block executes as normal and then all non-null resources of the try-with-resources statement are closed.

Resources are closed in the reverse order from that in which they were initialized. A resource is closed only if it initialized to a non-null value. An exception from the closing of one resource does not prevent the closing of other resources. Such an exception is suppressed if an exception was thrown previously by an initializer, the try block, or the closing of a resource.

What is more, Implt1#close() won't be called unless it is explicitly called inside of Impl2#close()

In short, it is better to declare multiple resources in separate statements separated with ;, like so:

try(Impl1 impl1 = new Impl1(); 
    Impl2 impl2 = new Impl2(impl1))
like image 107
Amongalen Avatar answered Oct 05 '22 00:10

Amongalen