As tzaman said, the secret is using finally; generally:
Resource r = allocateResource();
try {
// use resource
}
finally {
r.dispose();
}
Things to note here:
- try and finally each create a variable scope. So allocating your resource within the try clause won't work, as it won't be visible in the finally clause- you've got to declare the resource's variable before the try statement.
If you have several resources to allocate, the general pattern applies cleanly, but this is often not evident to beginners:
Resource1 r1 = allocateResource1();
try {
// code using r1, but which does not need r2
Resource r2 = allocateResource2();
try {
// code using r1 and r2
}
finally {
r2.dispose();
}
}
finally {
r1.dispose();
}
, and so on and so forth if you have more resources to allocate. If you have a couple of them, you will surely be tempted to try and avoid deep nesting of try... finally statements. Don't. You can get resource deallocation and exception handling right without nesting so many try... finally statements, but getting it right without nesting try... finally is even uglier than deep nesting.
If you frequently need to use a set of resources, you can implement a functor-based method to avoid the repetition, something like:
interface WithResources {
public void doStuff(Resource1 r1, Resource2 r2);
}
public static void doWithResources(WithResources withResources) {
Resource r1 = allocateResource1();
try {
Resource r2 = allocateResource2();
try {
withResources.doStuff(r1, r2);
}
finally {
r2.dispose();
}
}
finally {
r1.dispose();
}
}
Which then you can use like this:
doWithResources(new WithResources() {
public void doStuff(Resource1 r1, Resource2 r2) {
// code goes here
}
});
doWithResources will automatically handle allocation and deallocation correctly, and your code will have less repetition (which is a good thing). However:
- Java's syntax for anonymous classes is excessively verbose
- Checked exceptions within doStuff complicate things too much
, two points which I hope will be solved in Java 7.
You can find this kind of code throughout Spring, for instance: