When is it OK to catch NullPointerException?
Asked Answered
C

10

26

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?

Cage answered 16/8, 2013 at 4:43 Comment(2)
Usually 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
As mentioned @SayemAhmed, this signifies logical error, however it is upto you what you want to do even if you want to catch, you dont necessary do printStackTrace(). Normally you might have seen specially on user interfaces message showing something bad occurred with no information those are always these category of exceptions, so it is up to you to decide in calling code action you want to take or incase you are catching in called code then you can decide to throw it or take appropriate action.Groundage
G
52

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.

Goldsmith answered 16/8, 2013 at 5:37 Comment(2)
So much dressing, philosophy, and preparation for nulls. What do you think of using Kotlin instead of Java to handle a lot of this?Aliaalias
Optional in Java 8 is, unfortunately, not recommended as a field since it is not Serializable. You can either create your own implementation of Optional, or use null as a meaningful value for being absent. When you use null, you can let the getter return an Optional. Use self encapsulate field (i.e. use getter) within your class to avoid NPE and if's like (field == null).Gerrygerrymander
F
2

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")
}
Ferrochromium answered 16/8, 2013 at 4:49 Comment(0)
P
2

Generally It is recommend that one should not catch NullPointerException and let it be handled by JVM.

But it all depends, Say for eg: if you have code like List<Student> listStudent = getAllStudent();

here getAllStudent() connects to DB and give you result, Here before doing any operation on list object you should check that

if(listStudent != null){ 
    //do the task. 
}else{ 
    //Show Message like no student is there instead of catching NullPointerException 
}

if you will not do, then chances are there that NullPointerException can occur if no data is there.

so better practice is to check for Nulls but not handle it like

try{ 

}catch(NullPointerException e){

}
Planetstruck answered 16/8, 2013 at 4:51 Comment(3)
In reality, your example shows why it is a BAD IDEA to catch NPEs. Why? Consider what happens if "// do the task" throws an NPE. Ooops! Your catch block is now throwing away the evidence of a bug!Goldsmith
if you feel // do the task" has some code that can throw NPE then, it would be better practice to first check that the object there is null or not and if not null then only do operations. It is not with xyz line but at all the places i feel we should first check object for null, and if not then only proceed.Planetstruck
The problem with that approach is that it assumes that you have correctly analysed the code to determine whether an NPE is possible ... AND ... that analysis will continue to be valid in the face of future changes to the code. This is unrealistic, unless you know some high-level magic that prevents writing of buggy code.Goldsmith
U
1

You definetly should not use empty catch block without REALLY IMPORTANT reason. Usually there is no such reason.

Usually it's good either to check if variable is null or catch NPE and trow more appropriate reason. For example if a method getCar() returned null you may catch NPE on trying to call some method of the car, or check if the car is null and throw RuntimeException(but only if the situation is really exceptionable). Thus you make errors more abstract-binded and easier to understand.

Unsparing answered 16/8, 2013 at 4:51 Comment(0)
T
1

When an exception is thrown, be it any exception, jvm looks for the closest handler(catch block). If it is not found in the current method, it looks for the handler in the calling code and so on. SO basically the entire calling stack is searched bottom-up to look for a catch block which can handle the said exception. If no handler is found jvm uses the default handler which calls the e.printStackTrace()

Now NullPointerException is a runtime exception, which basically points to some logical fallacy in the code. There are times when you may want to catch it. But as a thumbrule:

  • don't catch runtime exceptions, they generally point to logical errors
  • don't leave an empty catch block, you will lose the stacktrace and the exception if you catch it but do not act upon it.
  • don't just print the stacktrace to standard outout, instead log it somewhere for later analysis, if needed
Trivandrum answered 16/8, 2013 at 4:54 Comment(0)
P
1

The convention is to avoid catching any sort of runtime exception. The reason being: something horrible has gone wrong, and you as a developer should be keen on fixing it thirty minutes ago.

NullPointerException is, in fact, a subclass of RuntimeException. Like other classes that have a parent of RuntimeException, they are considered unchecked - so code compiles even if it's going to produce an NPE:

// This would appropriately return "false", if the order were reversed 
// and something was empty.
public boolean doSomething(String something) {
    String hello = null;
    if(hello.equals(something)) {
        System.out.println("Wow");
    }
}

Explicitly catching any sort of runtime exception indicates that you expect horrible, bad things to happen over the course of the program, and you wish to gloss over that fact.

As for what goes in the body of the catch block...that's probably being automatically generated by your IDE. If you're not propagating the exception to the higher levels of your application, then you need to get useful context as to why your program blew up.

If you don't put anything in the catch block, it's silently ignored - which is bad.

Ploughshare answered 16/8, 2013 at 5:10 Comment(0)
C
1

Usually NullPointerException signifies a logical error in the API usage or exepcted value is missing. That's why it's recommended to to throw it back. However you can catch it. Practically

I will suggest you to catch when you want to give default values for the passed null parameters.

For example :

You are expecting timeout value to be configurable and you expect that user has to pass it. However user forgets to pass it. In this scenario you can catch the NPE and log a warning that you are using the default value for the parameter.

Circumpolar answered 16/8, 2013 at 5:13 Comment(0)
L
1

NullPointerException is a situation in code where you try to access/ modify an object which has not been initialized yet.

It essentially means that object reference variable is not pointing anywhere and refers to nothing or ‘null’.

Joshua bloch in effective java says that:

“Arguably, all erroneous method invocations boil down to an illegal argument or illegal state, but other exceptions are standardly used for certain kinds of illegal arguments and states. If a caller passes null in some parameter for which null values are prohibited, convention dictates that NullPointerException be thrown rather than IllegalArgumentException.”

So, if you must allow NullPointerException in some places in you code then make sure you make them more informative then they usually are.

Read more about Effective NPE Handling from here:

Londalondon answered 16/8, 2013 at 5:20 Comment(0)
U
-1

You dont have to actually do e.printstacktrace() all the time , you can specify your own body message using logger or System.out.println()

Uralite answered 16/8, 2013 at 4:47 Comment(0)
D
-1

Robust, user centric code should try to catch such a 'FATAL ERROR' if there is anything ANYTHING at all you could do about it. You could retry the attempted function call. Perhaps this null exception is due to something transient. Something that really shouldn't throw an exception and should be coded better for the transient failure but, which, however should not deter the end user from getting what he wants, instead of abandoning what could be a lengthy stateful form input process, and only on the last, completely insignificant step, like entering the users's email preference or something does the null pointer error occur and trash the user's existing input.

Dit answered 21/8, 2013 at 20:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.