How to avoid Null Pointer Exception in Java

How to avoid Null Pointer Exception in Java

This is a fairly common problem I see with beginning to intermediate programmers. They don't know or trust the conventions they are using, and are careful about checking for null. Also, when they write code, they often rely on returning NULL to indicate some meaning, and therefore require the caller to check for Null.

To put it another way, there are two scenarios where a null pointer check can occur:

A reasonable response in terms of the agreement

Not a reasonable response

The second is very simple, you can use assert or directly allow failure, such as NullPointerException. Assertions are a highly underused feature added since Java 1.4, the syntax is:

  1. assert <condition>

or

  1. assert <condition> : <object>

condition is a boolean expression and object is an object (the output of its toString() method will be included in the error).

If condition is false, assert will throw an Error (AssertionError).

By default Java will ignore assertions. You can enable assertions by passing a -ea parameter to the JVM.

You can enable or disable assertions for a single package or class. This means you can verify your code with assertions during development and testing.

Turn it off when shipping to production, although the tests I show below show no performance loss due to assertions.

This code snippet can be run without assertions, because it will fail just like it would with assertions. The only difference is

With assertions this may happen faster, make more sense, and add some extra information that can help you figure out

Reason for failure.

The first one is a little tricky. If you don't have control over the code being called, you're stuck.

If Null is a reasonable return value, you should check for it.

If it's code you control, it's a completely different story. Try to avoid using NULL as a return value.

For collections that return Collections, it's easy to return Empty (an empty collection or array) instead of always using null as the return value.

For methods that do not return Collections, things get a little more complicated. Consider the following example:

  1. public   interface Action {
  2. void doSomething();
  3. }
  4.  
  5. public   interface Parser {
  6. Action findAction(String userInput);
  7. }

A Parser takes user input as an argument and does something with it (e.g. simulates a command line). Now you might

Returns null if no action corresponding to the input is found, which leads to the null pointer check just mentioned.

An alternative solution is to never return null, but instead return an empty object.

  1. public   class MyParser implements Parser {
  2. private   static Action DO_NOTHING = new Action() {
  3. public   void doSomething() { /* do nothing */ }
  4. };
  5.  
  6. public Action findAction(String userInput) {
  7. // ...  
  8. if ( /* we can't find any actions */ ) {
  9. return DO_NOTHING;
  10. }
  11. }
  12. }

Compare this code:

  1. Parser parser = ParserFactory.getParser();
  2. if (parser == null ) {
  3. // now what?  
  4. // this would be an example of where null isn't (or shouldn't be) a valid response  
  5. }
  6. Action action = parser.findAction(someInput);
  7. if (action == null ) {
  8. // do nothing  
  9. } else {
  10. action.doSomething();
  11. }

and this paragraph:

  1. ParserFactory.getParser().findAction(someInput).doSomething();

This is a better design because it is concise and avoids unnecessary judgment. Even so, it might be more appropriate to have the findAction() method throw an exception with some meaningful error message - especially in this case where you rely on user input. It is much better to have the findAction() method throw an exception instead of simply generating a NullPointerException without any explanation.

  1. try {
  2. ParserFactory.getParser().findAction(someInput).doSomething();
  3. } catch (ActionNotFoundException anfe) {
  4. userConsole.err(anfe.getMessage());
  5. }

Or maybe you think the try/catch mechanism is too ugly and your action should provide a feedback to the user instead of doing nothing:

  1. public Action findAction( final String userInput) {
  2. /* Code to return requested Action if found */  
  3. return   new Action() {
  4. public   void doSomething() {
  5. userConsole.err( "Action not found: " + userInput);
  6. }
  7. }
  8. }

<<:  In-depth understanding of viewport in mobile front-end development

>>:  Greedy UIButton in Swift

Recommend

How a newbie can enter the film and television commentary track from 0 to 1

How can a novice enter the film and television co...

Was global warming first proposed by astronomers?

Author | Zhou Yihao Review | Zheng Chengzhuo Edit...

Xiaomi Notebook Air: The hard part is not just the ridiculous PPT

On July 27, Xiaomi, a well-known domestic mobile ...

What are these black spots on the edge of bus glass used for?

Image source: Tuchong Creative What are these bla...

Online marketing solutions for the real estate industry!

The real estate industry is a typical highly cycl...

Using Flink as an example to dispel six common myths about stream processing

We spend a lot of time thinking about stream proc...

AI Market Report

Marketing and sales departments are taking AI and...

5 tips to improve your YouTube search ranking!

We will introduce some methods to improve the fac...