Working with the final block
I have code that generates JarFile
and URLClassLoader
, both of which I want to close at the end. Naturally, I decided to use a block finally
to handle the cleanup:
JarFile jar = ...;
URLClassLoader loader = ...;
try {
// work ...
} finally {
jar.close();
loader.close();
}
However, both close()
invocations can throw an exception, so if jar.close()
it throws an exception it loader.close()
will not be achieved. One of the ways I thought about this is by surrounding it jar.close()
with a try-catch block:
JarFile jar = ...;
URLClassLoader loader = ...;
try {
// work ...
} finally {
try {
jar.close();
} catch(IOException e) {
}
loader.close();
}
But it seems ugly and over the top. Is there an elegant way to handle cleanup exceptions in blocks finally
?
source to share
In Java 7 and above there is an attempt with resources that handle objects Closeable
.
Reformat your code this way
try(JarFile jar = ....; URLClassLoader loader = ....;)
{
// work ...
}
Only classes that implement the interface Closeable
will work in this way, both of these classes meet these criteria.
source to share
Of course there is a way to encapsulate this, it's called a method! For example, you can create a class IOUtils
like this:
public class IOUtils {
// this class is not meant to be instantiated
private IOUtils() { }
public static void closeQuietly(Closeable c) {
if (c == null) return;
try {
c.close();
} catch (IOException e) { }
}
}
And then,
JarFile jar = ...;
URLClassLoader loader = ...;
try {
// work ...
} finally {
closeQuietly(jar);
loader.close();
}
As Patrick J Abae II said, you can also use try-catch with resources, but you can't always do that, for example if you create InputStream
in try-catch first and then create several different types InputStream
by encapsulating the first (ex: encapsulating in CipherInputStream
to decrypt the data and then write c FileOutputStream
). However, I am not saying that trying to try-catch with resources is not a useful construct, it is enough in most cases.
source to share
Use try-with-resources :
try (JarFile jar = new JarFile(filename);
URLClassLoader loader = URLClassLoader.newInstance(urls)) {
// do stuff
} catch (IOException ex) {
// handle ex
}