Possible Duplicate:
Static fields on a null reference in Java
I understand that static methods are on class level. So I am aware that I do not need to create instance to call static methods. But I am also aware that I can call static method LIKE an instance method. This is where I am confused, because I was expecting a NullPointerException
while calling the static method from the null object (as in calling instance method). I would really appreciate some explanation on why I was wrong to expect a NullPointerException
here.
Here is the sample code:
public class SampleClass {
public static int getSumStatic(int x, int y){
return x+y;
}
public int getDifferenceInstance(int x, int y){
return x-y;
}
}
public class TestClass {
public static void main (String[] args){
SampleClass sc=null;
System.out.println(SampleClass.getSumStatic(2, 2)); //as expected
//I was expecting NullPointerException in the next line, since I am accessing null object
System.out.println(sc.getSumStatic(4,5)); //static method , executes perfectly
System.out.println(sc.getDifferenceInstance(6,4));//throws NullPointerException
}
}
You are accessing a static method through a variable which is strongly typed to
SampleClass
. During compilation the method is resolved as being called directly on the class definition (hence it's a static method) so it is actually resolved.There is no implicit
this
inpublic static int getSumStatic
so there is no access to a null pointer.This is some kind of a design mistake from the java designers. You should call a static method on the class, because it belongs to the class and not to an object.
You can see a bit about this issue at why-isnt-calling-a-static-method-by-way-of-an-instance-an-error-for-the-java-co
The funny thing, it would not be possible to call a static method on an object variable which has not been initialized. But if the object is initialized with null, everything is fine.
I think this works because the object stored with this variable provide the type information through the assignment.
won't compile because the object is not initialized, therefore no type information is set in the syntax tree of the java compiler.
I think static functions for a class instance instance are basically replaced with their static class info at compile time(they also don't work with inheritance like instance methods).
Instance method tries to access null's methods and throws a NullPointerException.
As an additional note to dasblinkenlight's (absolutely correct) response, you can see the difference in the Java bytecode that gets generated (which you can see readably with
javap -c
).Consider the following (simpler) class:
And an application which uses it:
Let's look at the bytecode generated for
ExampleApplication.main(String[])
:Stepping through this (by offset, which is the numeric column in the above output):
The instructions at offsets 0 and 1 load
null
and then store it into local variable 1 (ex
).The instruction at offset 2 does a traditional static call: it's an
invokestatic
instruction which invokesExample.staticMethod()
. This doesn't involve the instance variable, as you expect.Next up is the call to the static method on our instance. The instruction at offset 5 loads
ex
onto the stack (remember that this is null), but thepop
at offset 6 undoes this immediately. So theinvokestatic
at offset 7 behaves exactly the same as the one at offset 2: the null value isn't on the VM stack, and the method to be invoked is compiled in byjavac
, regardless of what the value ofex
is.By contrast, a virtual (i.e. non-static) method pushes the instance onto the stack (offset 10), and then while it's on the stack, executes an
invokevirtual
instruction which looks upvirtualMethod()
on the instance to find the method to execute. This is the step where aNullPointerException
is thrown, since that lookup cannot proceed. (Note that this step is unnecessary in the static case, which is also why static method calls are faster in a naive VM.)Calling a static method through an instance does not require the instance to be there. As long as the compiler is able to determine the type of the variable, it makes the equivalent call statically after evaluating the
sc
expression and discarding the result:From the Java Language Specification:
Java will allow you to access the static method based simply on the reference, even when the reference is
null
. Only the type of the reference is important.You should generally use the class name to call static methods: