16

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
    }
}
Community
  • 1
  • 1
Jimmy
  • 2,589
  • 21
  • 31
  • 5
    This question has been asked very, very often on StackOverflow. Examples: http://stackoverflow.com/questions/11579953/static-fields-on-a-null-reference-in-java and http://stackoverflow.com/questions/8042103/accessing-a-static-field-with-a-null-object-in-java – Ray Toal Sep 30 '12 at 22:02
  • 1
    The other questions are about accessing static *fields*; this question is about accessing static *methods*. The questions share some degree of similarity, but they are definitely not *exact duplicates* of each other. – Sergey Kalinichenko Oct 01 '12 at 14:25
  • On top of that, based on the upvotes on the question and the answers, I bet lots of programmer learned new things ,including me. I actually came across this particular scenario at my work , so I like to thank all the users who helped me understand it better. – Jimmy Oct 01 '12 at 15:06

6 Answers6

14

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:

System.out.println(SampleClass.getSumStatic(4,5));

From the Java Language Specification:

Section 15.12.1

❖ If the form is Primary.NonWildTypeArgumentsopt Identifier, then the name of the method is the Identifier. Let T be the type of the Primary expression. The class or interface to be searched is T if T is a class or interface type, or the upper bound of T if T is a type variable.

Section 15.12.4.1:

  1. If the second production for MethodInvocation, which includes a Primary, is involved, then there are two subcases:

❖ If the invocation mode is static, then there is no target reference. The expression Primary is evaluated, but the result is then discarded.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
3

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.

SampleClass sampleObject;
sampleObject.getSumStatic(2, 2) 

won't compile because the object is not initialized, therefore no type information is set in the syntax tree of the java compiler.

Community
  • 1
  • 1
Jan Koester
  • 1,178
  • 12
  • 26
2

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:

SampleClass.getSumStatic(2, 2);
pb2q
  • 58,613
  • 19
  • 146
  • 147
2

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:

public class Example {
  public static void staticMethod() {}
  public void virtualMethod() {}
}

And an application which uses it:

public class ExampleApplication {
  public static void main(String[] args) {
    Example ex = null;
    Example.staticMethod();
    ex.staticMethod();
    ex.virtualMethod();
  }
}

Let's look at the bytecode generated for ExampleApplication.main(String[]):

public static void main(java.lang.String[]);
  Code:
   0:   aconst_null
   1:   astore_1
   2:   invokestatic    #2; //Method Example.staticMethod:()V
   5:   aload_1
   6:   pop
   7:   invokestatic    #2; //Method Example.staticMethod:()V
   10:  aload_1
   11:  invokevirtual   #3; //Method Example.virtualMethod:()V
   14:  return

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 invokes Example.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 the pop at offset 6 undoes this immediately. So the invokestatic 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 by javac, regardless of what the value of ex 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 up virtualMethod() on the instance to find the method to execute. This is the step where a NullPointerException 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.)

Jeremy Roman
  • 16,137
  • 1
  • 43
  • 44
1

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 in public static int getSumStatic so there is no access to a null pointer.

Jack
  • 131,802
  • 30
  • 241
  • 343
0

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.

Roman A. Taycher
  • 18,619
  • 19
  • 86
  • 141