Effective java recommend that we shouldn't catch NullPointerException. Is it always right?
In nearly all cases it is correct.
NullPointerException
is usually a result of a bug; i.e. your application encountered a null
object reference in a situation where it was not anticipated, and then attempted to use it. In this scenario, since you (the programmer) did not anticipate the null
, it is next to impossible to know whether it is safe to attempt to recover, and / or to know what "remediation" might be required. So the best thing to do is to let the NPE propagate to the base level, and then treat it as a generic bug. (In "network service" applications, it may be appropriate to return a "service error" response, and attempt to continue.)
The other scenario is where you (the programmer) anticipate that a null
might be delivered. In this case, the best strategy is (nearly always) to explicitly test for the null
before you attempt to use it, thereby avoiding the NPE ... and the need to handle it. There are two reasons for this:
Exception handling is typically expensive. Indeed it can be many orders of magnitude more expensive than testing for a null
.
If you allow the expected NPE to happen and then catch it, you are liable to also catch other unexpected NPEs ... and handle them incorrectly.
Note that I qualified the above by saying "nearly always". It is theoretically possible to have a scenario where explicit tests for null
clutter up your code so much that it is at least worth considering allowing the NPE to happen. However, there is still the possibility of unexpected NPEs as well ... depending on the code. So this approach is always potentially fragile.
(FWIW - I've never encountered a real case where this would be a good idea ...)
In many cases of catching NullPointerException, catch body only calls printStackTrace().
That is probably bad code. Doing nothing is rarely the correct way to recover from an NPE.
If I don't catch NullPointerException and call printStackTrace(), how I can check the place where the exception occurred?
You let the NPE propagate to the base level. There you catch and print (or log) a stacktrace for all unhandled exceptions, and then either bail out or attempt to recover ... if that is feasible.
And also if I catch NullPointerException and the catch body is empty, we cannot get any stack information at that time, can we?
Never, ever do this! It is called "squashing" and is dangerous. (Especially since, as I explained above, the NPE may be due to something that you / your code did not anticipate.)
And no, if you do this, you can't get the stack trace. It is gone.
FOLLOWUP
I don't place much trust / faith on some general strategies for "avoiding NPEs"1. For instance stuff like this:
return (someObject != null) ? someObject.toString() : "";
always make me suspicious that the programmer is not thinking about the problem. Why was someObject
a null
in the first place?
A NPE is caused by having a null
in place where you don't expect it. As such, NPEs are usually symptoms of a problem rather than the actual problem itself. To my mind, NPEs are not something to be avoided. Rather, you should be using the NPEs to find and fix the root cause of the unexpected null
. Code like the above that avoids the NPE gets in the way of that goal.
So I prefer / recommend strategies for avoiding null
values in unexpected places.
Make sure that every reference field is gets initialized to a non-null value ... unless null
is a meaningful value.
Try to avoid having null
as a meaningful value, especially if there is an alternative. For instance, an empty String, a zero length array, an empty collection, a distinguished instance that means "undefined" or whatever. Or, for Java 8 and later, use Optional
.
Don't return null
as an error or an indication of a special case. (Throw an exception or return a distinguished value.)
Check early for unanticipated null
values (e.g. null
arguments), and throw the NPE sooner rather than later.
In the few places where a null
argument or result is legitimate, make sure that your javadocs document this clearly and explicitly. If there is no documentation, then the implication should be that null
is not allowed and won't be returned.
And wherever you get an NPE, make sure that you find and fix the real source of the problem ... not just the specific statement that threw the exception.
1 - There is value in knowing about places in the standard Java APIs where null
is used (or abused) as a return value. For instance, Class.getResourceAsStream(...)
or HttpRequest.getParam(...)
. Those "advice for avoiding NPE" documents are useful in as much that they point out these traps.
NullPointerException
signifies some sort of logical error in the program. That's why it's recommended to eliminate them totally. If it occurs, you can easily see the stack trace in the console. – Promiscuity