I tend to write code like the following a lot:
BufferedWriter w = null; // Or any other object that throws exceptions and needs to be closed
try {
w = new BufferedWriter(new FileWriter(file));
// Do something with w
} catch (IOException e) {
e.printStackTrace();
} finally {
if (w != null) {
try {
w.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
It usually involves an object that throws exceptions and needs to be closed, and that closing it may also throw an exception.
I was wondering if the above code can be simplified or reused in any way.
Java provides two different options to handle an exception. You can either use the try-catch-finally approach to handle all kinds of exceptions. Or you can use the try-with-resource approach which allows an easier cleanup process for resources.
The try-catch is the simplest method of handling exceptions. Put the code you want to run in the try block, and any Java exceptions that the code throws are caught by one or more catch blocks. This method will catch any type of Java exceptions that get thrown. This is the simplest mechanism for handling exceptions.
If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.
If you don't want to write code for closing in finally block, you should have a look at Project Lombok
Instead of writing the normal
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
}
With Lombok you can write
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
Much more readable, and it generates the correct way of closing the Stream. This works with all the Closeable
interfaces
I usually put contents of your finally
block in a helper. Like this
void close(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException e) {
// perform logging or just ignore error
}
}
}
Closeable
interface is implemented by many classes (input streams, database connections, etc), so this is kinda general-purpose helper.
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