What your code does is:
- invoke some methods
- if it throws an exception, log (or whatever) the error and return null
- otherwise return what it returns
The cleanest way to do this -- and this is not new -- is:
try {
return someMethod(...);
} catch (SomeException e) {
logOrWhatever(e);
return null;
}
Some people object to multiple return
s -- but in a short block like this, it's the clearest way (and if your block isn't this short, do the extract-method refactoring until it is).
The alternative with just one return
is longer and messier, and involves declaring a mutable variable in a wider scope than necessary:
Foo response = null;
try {
response = someMethod(...);
} catch (SomeException e) {
logOrWhatever(e);
}
return response;
- It has more clutter. Think about how much reading you have to do to answer the question "What does this method return if
someMethod()
throws an exception?". In the first example it's right there in the catch
block. In the second you have to follow the code up through all possible state changes to response
.
response
can't be declared final
-- I don't think you should use final
everywhere, but I do think it's good to have as many variables as possibly that could be declared final.
- The scope of
response
is outside the try
block. The tidier method keeps that data in a narrower scope, which is always good.
By putting the return
in a finally
block, your code does something else -- if any other type of exception is thrown, null
will be returned without any logging or other exception-handling. This is unlikely to be a good idea -- it just makes bugs hard to diagnose: Try-catch-finally-return clarification
However, more generally, returning null is something you should try to avoid. Your question title mentions "null-management", but it's you that has introduced a null to proceedings. If you didn't choose to return null, you wouldn't have to deal with its problems:
- If null means "something went wrong", don't do that. Handle the exception higher up (if you like, re-throw it as a different exception type)
- If the semantics of the method are "This might return a response, or there may not be a response", consider:
- Making the method return
Optional<Response>
-- now the method signature is honest
- Using the "Null object" pattern. That is, instead of returning
null
return new EmptyResponse()
This way more of your code can be much simpler and cleaner, because it doesn't have to be full of if(x==null)
guards.