Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it OK to catch NullPointerException?

Tags:

Effective java recommends that we shouldn't catch NullPointerException. Is it always right?

In many cases of catching NullPointerException, catch body only calls printStackTrace().

If I don't catch NullPointerException and call printStackTrace(), how I can check the place where the exception occurred?

And also if I catch NullPointerException and the catch body is empty, we cannot get any stack information at that time, can we?

UPDATE

I analyzed statistics of catching RuntimeException in google android source, AOSP4.2.2_r1.2.

There are 249 RuntimeException catchings and followings are statistics of catch-body.

42%: throw it again as other Exceptions (RuntimeException: 33%, others: 8%)  32%: just return null or 0/false/true or other default values  14%: just call log or printstacktrace  5%: just comment like "// Fall through.", "// ignore, not a valid type.", "// system process dead", "// do nothing"  2%: empty body  3%: display error messages or send fail codes (ex. network service discovery failed: replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, NsdManager.FAILURE_INTERNAL_ERROR); )   3%: intialize or reset related variables. 

In almost cases, dalvik and external handle NPE by throwing other Exceptions.

But frameworks usually handle by returning null or other values.

  1. Do you think that throwing other Exceptions in catch-body is not bad or good handling?

  2. If NPE occured in higher levels(ex. applications) and the developer confirms the exception is not critical because the app is fully independent, can I accept for our developer to ignore the NPE by catching?

and one more thing,

Can I conclude that google android framework source code may be some unstable in aspects of RuntimeException?

like image 295
500004dolkong Avatar asked Aug 16 '13 04:08

500004dolkong


2 Answers

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.

like image 75
Stephen C Avatar answered Sep 29 '22 15:09

Stephen C


NullPointerException typically occurs due to logical errors in our code. We can eliminate NullPointerException by avoiding unsafe operations. If any NullPointerException still happens, you can see it in StackTrace.

For example

if (Obj.getName("Sam")) {     // only executes if Obj != null }   

We can avoid NullPointerException as follows

if (Obj == null){     System.out.println("Null Obj, Can't proceed"); } else {     Obj.getName("Sam") } 
like image 45
Ruchira Gayan Ranaweera Avatar answered Sep 29 '22 16:09

Ruchira Gayan Ranaweera