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

Depression is not hypocrisy. You need to know these rumors about depression.

Author: Le Dansheng Department of Clinical Psycho...

How to promote to KOL? Here are 3 ways!

Why do KOLs ignore me? How to convince KOL to pro...

Search Promotion | Four Principles of Data Analysis

Many friends want to learn data analysis, so I wi...

Case analysis: Wedding photography advertising case in WeChat Moments!

With the continuous evolution of consumption upgr...

Short video operation: VLOG "script" writing guide

“You just need to master the vlog method You can ...

What do the blue, yellow, orange and red rainstorm warning signals mean?

I guess you must have received a text message lik...