Search This Blog

Tuesday, June 16, 2009

When Explicitly Initializing Class Variables to null Matters

You can't just willy-nilly do anything in Java because it 'looks good' - aside from formatting of course - and even certain ways of formatting can have an effect on code initialization, such as ordering of class/instance variables and static initialization blocks.

Here is an example where understanding what actually happens when an instance variable is explicitly initialized to null will cause a null-pointer to occur even though it is initialized to a non-null value in an implemented abstract method that is called by the super constructor.

In the following example, the abstract class has one abstract method, doConcreteStuff1, that is intended to be invoked in the constructor of the same class: concrete classes need only implement doConcreteStuff1(). Here we have explicitly set instance variables 'one' and 'two' to null and we initialize them in the implemented doConcreteStuff() method.



What do you think will happen when the code is executed?

When the code is executed the following occurs:

B:One is one
B:Two is two
Exception in thread "main" java.lang.NullPointerException
at base.InstanceVarNull$ConcreteInstanceVarNull.(InstanceVarNull.java:16)
at base.InstanceVarNull.main(InstanceVarNull.java:28)

:banghead: UGhhh!! A null-pointer!!!!

Is that what you expected? After all, we did initialize them to non-null values, but it appears that they were overwritten back to null! What gives?

Let's demonstrate another example. I'll remove the explicit null initialization from the instance variables.



What do you think will happen this time when the new code is executed?

When the code is executed the following occurs:

B:One is one
B:Two is two
A:One is one
A:Two is two

No null-pointer!!! :eek:

The question here is, why?

By explicitly assigning null to the instance variables (in example 1), the compiler will insert the assignment in the constructor of the concrete class and due to the order of operations, doConcreteStuff1() will indeed get executed BEFORE this assignment. So we will see 2 statements being printed, but after that the concrete class will then initialize and re-assign those variables to null.

However, in the second example, we DO NOT explicitly assign null to the instance variables and the compiler does not assign them as null in the constructor. So when we execute example 2, the only assignment for those variables occurs in the doConcreteStuff1() method, and we have NO null-pointers.

Check out the byte-code of each example if you don't believe me.

Cheers and happy coding! :beerchug:

I thought I would add the de-compiled class files to prove my claim:

Here is the generated class file with null explicitly set (example 1, above), more specifically I show the constructor:
Note lines 5 and 10.



, and here is the generated class file with null NOT explicitly set (example 2, above), more specifically I show the constructor:
Note that the null assignment DOES NOT occur in the constructor as it does above, which is the reason why the values do not get overridden and hence no null-pointer!!!! :jumpingjoy: :jumpingjoy: