By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,946 Members | 1,600 Online
Bytes IT Community
Submit an Article
Got Smarts?
Share your bits of IT knowledge by writing an article on Bytes.

NullPointerException a.k.a NullReferenceException

10K+
P: 13,264
This exception occurs often enough in practice to warrant its own article. It is a very silly exception to get because it's one of the easiest exceptions to avoid in programming. Yet we've all got it before, lending proof to Einstein's statement: “Only two things are infinite, the universe and human stupidity ...”.

Main Cause

Dereferencing null.

This is by far the more common cause of getting the exception.

Reference types in both Java and .NET have a default value of null. A variable of a reference type whose value is null indicates that that variable is pointing to no object. Nothing. You can do very little with nothing. You certainly can't dereference it without summoning the NullPointer exception to come and smack you with you the stupidity label. So if we have
Expand|Select|Wrap|Line Numbers
  1. Type var = null;
We have created a variable of type Type, named it var, and made it point to no object. If we dot (apply the dereferencing operator(.)) var we are going to get the NullPointer exception because we will have dereferenced no object. We have asked nothing to do something. Very stupid indeed. var needs to be pointing to some non-null object for us to be able to dereference it. Possible solutions are
Expand|Select|Wrap|Line Numbers
  1. var = new Type();
or
Expand|Select|Wrap|Line Numbers
  1. var = anotherVar;
where anotherVar is a reference to a previously initialized object.

This all sounds very simple doesn't it? Here are a few tips on how to avoid it.

Avoiding it


1.) Always declare variables closest to where they are used.

The old C way of declaring variables at the top leaves room for forgetting to initialize them before using them several lines later in the code. You don't get the NullPointer exception in C if you do forget. You simply get garbage.

2.) Careful with composites.

A statement such as
Expand|Select|Wrap|Line Numbers
  1. Type[] array = new Type[5];
creates a variable of type Type[], names it array and initializes it to an array object with 5 elements. The five elements in this array array[0], array[1], ..., array[4] unfortunately have default values of the Type type. If Type is a reference type then these values are all nulls. They each point to no object. Dereferencing any of array's indexes will cause the NullPointer exception to be thrown. Each of the five indexes of array need to made to point to non-null values before they can be dereferenced. Obviously the same holds for other collections and composite types.

3.) Beware of method/constructor variable hiding.

Expand|Select|Wrap|Line Numbers
  1.  
  2. class Person {
  3.     String name;
  4.  
  5.     public Person() {
  6.         String name = "Something Stupid";
  7.     }
  8.  
  9.     public String getFirstName() {
  10.         return name.split(" ")[0];
  11.     }
  12.  
  13.     public static void main(String[] args) {
  14.         Person stupid = new Person();
  15.         System.out.println(stupid.getFirstName());
  16.     }
  17. }
  18.  
In the code snippet above, the Person class has a name property which the constructor attempts to initialize. The attempt is hopeless. Instead a new name variable is created inside the constructor. The declaration of this variable hides the name property of the class inside that constructor. To add further insult, that name variable declared inside the constructor is only available inside that constructor. It is out of scope anywhere else outside that constructor.
When the unsuspecting main method calls the getFirstName method, the split is going to be called on a non initialized property. No prizes for guessing what ensures.
In general, care is needed when accessing instance variables that are not initialized when they are declared and local variables are best given names that do not clash with instance variable names.

4.)Read the relevant documentation.

Programmers are allowed to explicitly throw the NullPointer exception in their code for whatever reason they deem appropriate. This means that you can get the NullPointer exception without explicitly dereferencing a null variable but by executing code whose execution flow passes through a statement with a throws clause for the NullPointer exception.
A simple Java example is the java.util.Hashtable's contains method. The code for that method is
Expand|Select|Wrap|Line Numbers
  1.  public synchronized boolean contains(Object value) {
  2.     if (value == null) {
  3.         throw new NullPointerException();
  4.     }
  5.  
  6.     Entry tab[] = table;
  7.     for (int i = tab.length ; i-- > 0 ;) {
  8.         for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
  9.         if (e.value.equals(value)) {
  10.             return true;
  11.         }
  12.         }
  13.     }
  14.     return false;
  15.     }
  16. /*
  17.  * @(#)Hashtable.java    1.116 06/05/26
  18.  *
  19.  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  20.  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  21.  */
  22.  
As you can see here the NullPointerException is explicitly thrown if the parameter passed is null. Fortunately, we don't always have to guess which methods throw the nullpointer exception under what conditions. The documentation of the methods should explicitly tell us what conditions cause the method to throw that exception. This is always the case in well documented code and you should likewise document your code properly if you explicitly throw any exceptions under certain conditions.
So if we want to invoke the contains method of the Hashtable class with a parameter p, reading the documentation of that method tells us that we should check that our p is not null before invoking the method.

The same holds for JSP parameters and attributes. If a parameter is requested by the request.getParameter method and no parameter with that name exists in the request then null is returned. Any operations on the returned parameters may cause the NullPointer exception if the returned value is not checked for non null.

5.)Log whenever possible during development

Often enough, the exception is caused by falsely assuming certain data values and certain paths of execution. Sprinkling some print outs at critical positions will help to dispense some of those false assumptions and expose the holes where the nullPointer is most likely to try and sneak in through. Indeed I will go as far as saying that setting up the logging framework should be one of the first steps that should be done during system implementation.


6.) Beware of super class constructor initializations vs derived class instance initializers

There is another less obvious way of creating nulls all over the place. Indeed the following discussion may not be for the faint hearted :

In the snippet below ( especially prepared for our amusement by Jos)
Expand|Select|Wrap|Line Numbers
  1. abstract class BaseClass {
  2.  
  3.     abstract protected void initialize(String name);
  4.     public BaseClass(String memberName) {
  5.         initialize(memberName);
  6.         System.out.println("in base: " + this);
  7.     }
  8. }
  9. class NullMember extends BaseClass {
  10.     String    name    = null;
  11.     public NullMember(String memberName) {
  12.         super(memberName);
  13.     }
  14.  
  15.     @Override
  16.     protected void initialize(String name) {
  17.         this.name = name;
  18.     }
  19.  
  20.     @Override
  21.     public String toString() {
  22.         return name;
  23.     }
  24.  
  25.     public static void main(String[] args) {
  26.         NullMember nm = new NullMember("foo");
  27.         System.out.println("NullMember: " + nm);
  28.     }
  29. }
  30.  
The output is
Expand|Select|Wrap|Line Numbers
  1. in base: foo
  2. NullMember: null
  3.  
It appears in the main method that the variable name was never initialized even though the print outs do show that name indeed was “foo” at some point. This peculiarity is due to the order of execution of statements during object construction. The JLS (8.8.7) explains this as
Let C be the class being instantiated, let S be the direct superclass of C, and let i be the instance being created. The evaluation of an explicit constructor invocation proceeds as follows:
•First, if the constructor invocation statement is a superclass constructor invocation, then the immediately enclosing instance of i with respect to S (if any) must be determined. Whether or not i has an immediately enclosing instance with respect to S is determined by the superclass constructor invocation as follows:
<Here the JLS mumbles on in it’s lifeless tone to explain how to determine the immediately enclosing instance of i. Thankfully we are not concerned with any of that in this discussion>

• Second, the arguments to the constructor are evaluated, left-to-right, as in an
ordinary method invocation.
• Next, the constructor is invoked.
• Finally, if the constructor invocation statement is a superclass constructor
invocation and the constructor invocation statement completes normally, then
all instance variable initializers of C and all instance initializers of C are executed.
The last bit there is what we are interested in. If we are calling a super class constructor, any initializations that we will do in that constructor will be overwritten by calls to instance initializers in the calling (extending) class soon after the super class constructor is called. If the initializers in the inheriting class set any variables to null as in the example above, then we are treading in a field were some nullpointers have been set.
That said, there really isn’t much to gain at all by explicitly initializing instance fields to null. If we don’t provide it then we have left no explicit initializers to be used to overwrite all the good work that our super class constructor will have done.

Fortunately, this peculiarity does not exist for .NET programmers.
The equivalent C# example
Expand|Select|Wrap|Line Numbers
  1. abstract class BaseClass
  2.     {
  3.         public abstract void initName(String s);
  4.         public BaseClass(String s)
  5.         {
  6.             initName(s);
  7.             Console.WriteLine("in base "+this);
  8.         }
  9.  
  10.     }
  11.     class NullMember : BaseClass
  12.     {
  13.         String name = null; 
  14.        public NullMember(String s):base(s)
  15.         {
  16.  
  17.         }
  18.  
  19.         static void Main(string[] args)
  20.         {
  21.             NullMember p = new NullMember("foo");
  22.             Console.WriteLine("NullNumber "+p);
  23.             Console.ReadLine();
  24.         }
  25.         public override String ToString()
  26.         {
  27.             return name;
  28.         }
  29.         public override void  initName(String s)
  30.         {
  31.             this.name = s;
  32.         }
  33.     }
  34.  
is well behaved, printing “foo” both in the super class constructor and in the main method.
This behavior has the blessing of the C# Language specification (10.11.2) which says
When an instance constructor has no constructor initializer, or it has a constructor initializer of the form base(...), that constructor implicitly performs the initializations specified by the variable-initializers of the instance fields declared in its class. This corresponds to a sequence of assignments that are executed immediately upon entry to the constructor and before the implicit invocation of the direct base class constructor. The variable initializers are executed in the textual order in which they appear in the class declaration.
The variable initializers are executed before invoking the base class constructor meaning that the name = null part is the one that is overwritten by the constructor call and not the other way around.


Debugging it.

If you are getting this exception then you probably have a stacktrace listing the methods and or constructors that were invoked up to and including the exact line where this exception was thrown. The first thing to do with that trace is to identify the first line in the stack trace which comes from your code. That line will contain either an explicit dereference of a null variable of a call to some block of code which induces the nullPointer exception.
The first case is easy. Just test each of the dereferenced variables on that line to make sure that they are not null. The second case involves checking the documentation of the code you have invoked to understand what conditions will cause it to throw the exception and then to compare those conditions with the conditions in which you are invoking it.

Demonstrating with a Java example,
Expand|Select|Wrap|Line Numbers
  1. static Object key;
  2. static Hashtable<String, String> t = new Hashtable<String, String>() {
  3.     {
  4.         put("one", "entry");
  5.     }
  6. };
  7. public static void main(String[] args) {
  8.     System.out.println(t.contains(key));
  9. }
  10.  
you would get
Expand|Select|Wrap|Line Numbers
  1. Exception in thread "main" java.lang.NullPointerException
  2.     at java.util.Hashtable.contains(Hashtable.java:265)
  3.     at Person.main(Person.java:20)
  4.  
The first line that belongs to my code is Person.main(Person.java:20).
On that line I have
Expand|Select|Wrap|Line Numbers
  1. System.out.println(t.contains(key));
  2.  
Variables being dereferenced are t and out both of which are not null. The block of code I am invoking there is java.util.Hashtable's contains method and the condition that causes it to throw the NullPointer exception is if the parameter passed is null. My parameter, key, is never initialized to a non null value so that is the problem.
Of course stepping through with a debugger would lead one to the same conclusions.

Conclusion

Having read this article you may be enticed to think that you will never get the NullPointer or NullReference exception again. Such thinking is encouraged of course. It would be nice to prove Einstein wrong again.
Mar 9 '09 #1
Share this Article
Share on Google+
1 Comment


Expert 10K+
P: 11,448
I'm closing this thread; any discussions about NullPointerExceptions please post them in the 'answers' section of the Java forum.

kind regards,

Jos
Aug 17 '09 #2