I may be overthinking this, but I just wrote the code:
try (InputStream in = ModelCodeGenerator.class.getClassLoader().getResourceAsStream("/model.java.txt"))
{
modelTemplate = new SimpleTemplate(CharStreams.toString(new InputStreamReader(in, "ascii")));
}
Which means the InputStreamReader is never closed (but in this case we know its close method just closes the underlying InputStream.)
One could write it as:
try (InputStreamReader reader = new InputStreamReader(...))
But this seems worse. If InputStreamReader throws for some reason, the InputStream won't ever be closed, right? This is a common problem in C++ with constructors that call other constructors. Exceptions can cause memory/resource leaks.
Is there a best practice here?
The Java try with resources construct, AKA Java try-with-resources, is an exception handling mechanism that can automatically close resources like a Java InputStream or a JDBC Connection when you are done with them. To do so, you must open and use the resource within a Java try-with-resources block.
InputStreamReader will not close an interface. It will close the underlying data resource (like file descriptor) if it is. It will do nothing if close is override and empty in an implementation.
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. Any object that implements java.
For try-with-resources, if an exception is thrown in a try block and in a try-with-resources statement, then the method returns the exception thrown in the try block. The exceptions thrown by try-with-resources are suppressed, i.e. we can say that try-with-resources block throws suppressed exceptions.
Which means the InputStreamReader is never closed
Eh? In your code it is... And it will certainly handle the .close() of your resource stream as well. See below for more details...
As @SotiriosDelimanolis mentions however you can declare more than one resource in the "resource block" of a try-with-resources statement.
You have another problem here: .getResourceAsStream()
can return null; you may therefore have an NPE.
I'd do this if I were you:
final URL url = ModelCodeGenerator.class.getClassLoader()
.getResource("/model.java.txt");
if (url == null)
throw new IOException("resource not found");
try (
final InputStream in = url.openStream();
final Reader reader = new InputStreamReader(in, someCharsetOrDecoder);
) {
// manipulate resources
}
There is a very important point to consider however...
Closeable
does extend AutoCloseable
, yes; in fact it only differs, "signature wise", by the exception thrown (IOException
vs Exception
). But there is a fundamental difference in behavior.
From the javadoc of AutoCloseable
's .close()
(emphasis mine):
Note that unlike the close method of Closeable, this close method is not required to be idempotent. In other words, calling this close method more than once may have some visible side effect, unlike Closeable.close which is required to have no effect if called more than once. However, implementers of this interface are strongly encouraged to make their close methods idempotent.
And indeed, the javadoc of Closeable
is clear about this:
Closes this stream and releases any system resources associated with it. If the stream is already closed then invoking this method has no effect.
You have two very important points:
Closeable
also takes care of all resources associated with it; so, if you close a BufferedReader
which wraps a Reader
which wraps an InputStream
, all three are closed;.close()
more than once, there is no further side effect.This also means, of course, that you can choose the paranoid option and keep a reference to all Closeable
resources and close them all; beware however if you have AutoCloseable
resources into the mix which are not Closeable
!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With