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
- Type var = null;
Expand|Select|Wrap|Line Numbers
- var = new Type();
Expand|Select|Wrap|Line Numbers
- var = anotherVar;
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
- Type[] array = new Type[5];
3.) Beware of method/constructor variable hiding.
Expand|Select|Wrap|Line Numbers
- class Person {
- String name;
- public Person() {
- String name = "Something Stupid";
- }
- public String getFirstName() {
- return name.split(" ")[0];
- }
- public static void main(String[] args) {
- Person stupid = new Person();
- System.out.println(stupid.getFirstName());
- }
- }
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
- public synchronized boolean contains(Object value) {
- if (value == null) {
- throw new NullPointerException();
- }
- Entry tab[] = table;
- for (int i = tab.length ; i-- > 0 ;) {
- for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
- if (e.value.equals(value)) {
- return true;
- }
- }
- }
- return false;
- }
- /*
- * @(#)Hashtable.java 1.116 06/05/26
- *
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
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
- abstract class BaseClass {
- abstract protected void initialize(String name);
- public BaseClass(String memberName) {
- initialize(memberName);
- System.out.println("in base: " + this);
- }
- }
- class NullMember extends BaseClass {
- String name = null;
- public NullMember(String memberName) {
- super(memberName);
- }
- @Override
- protected void initialize(String name) {
- this.name = name;
- }
- @Override
- public String toString() {
- return name;
- }
- public static void main(String[] args) {
- NullMember nm = new NullMember("foo");
- System.out.println("NullMember: " + nm);
- }
- }
Expand|Select|Wrap|Line Numbers
- in base: foo
- NullMember: null
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:<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>
•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:
• Second, the arguments to the constructor are evaluated, left-to-right, as in anThe 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.
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.
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
- abstract class BaseClass
- {
- public abstract void initName(String s);
- public BaseClass(String s)
- {
- initName(s);
- Console.WriteLine("in base "+this);
- }
- }
- class NullMember : BaseClass
- {
- String name = null;
- public NullMember(String s):base(s)
- {
- }
- static void Main(string[] args)
- {
- NullMember p = new NullMember("foo");
- Console.WriteLine("NullNumber "+p);
- Console.ReadLine();
- }
- public override String ToString()
- {
- return name;
- }
- public override void initName(String s)
- {
- this.name = s;
- }
- }
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
- static Object key;
- static Hashtable<String, String> t = new Hashtable<String, String>() {
- {
- put("one", "entry");
- }
- };
- public static void main(String[] args) {
- System.out.println(t.contains(key));
- }
Expand|Select|Wrap|Line Numbers
- Exception in thread "main" java.lang.NullPointerException
- at java.util.Hashtable.contains(Hashtable.java:265)
- at Person.main(Person.java:20)
On that line I have
Expand|Select|Wrap|Line Numbers
- System.out.println(t.contains(key));
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.