When is it OK to catch NullPointerException?

2019-01-17 22:13发布

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?

10条回答
啃猪蹄的小仙女
2楼-- · 2019-01-17 22:50

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.

查看更多
神经病院院长
3楼-- · 2019-01-17 22:55

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.

查看更多
Melony?
4楼-- · 2019-01-17 23:01

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
查看更多
爷、活的狠高调
5楼-- · 2019-01-17 23:02

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.

查看更多
我命由我不由天
6楼-- · 2019-01-17 23:06

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.

查看更多
别忘想泡老子
7楼-- · 2019-01-17 23:07

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

查看更多
登录 后发表回答