27

I was pointing some tricks and came across this. In following code:

public class TestClass1 {

    static int a = 10;

    public static void main(String ar[]){
        TestClass1 t1 = null ;
        System.out.println(t1.a); // At this line
    }
}

t1 object is null. Why this code is not throwing NullPointerException?

I know this is not proper way to access static variables but question is about NullPointerException.

3
  • 2
    A pity (Java) compilers allow this, it's rather confusing. Does it even result in a warning? Commented Jan 10, 2014 at 12:19
  • 3
    @M.Mimpen If it is eclipse, Then warning goes on like The static field should be accessed in a static way :) Commented Jan 10, 2014 at 12:23
  • @M.Mimpen yes exactly it will...but it was about NullPointer. which is clear now. Commented Jan 10, 2014 at 12:26

7 Answers 7

27

There is no need for an instance while invoking static member or method.

Since static members belongs to class rather than instance.

A null reference may be used to access a class (static) variable without causing an exception.

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#d5e19846

If you see the example (see full example in spec)

 public static void main(String[] args) {
        System.out.println(favorite().mountain); //favorite() returns null
    }

Even though the result of favorite() is null, a NullPointerException is not thrown. That "Mount " is printed demonstrates that the Primary expression is indeed fully evaluated at run time, despite the fact that only its type, not its value, is used to determine which field to access (because the field mountain is static).

Sign up to request clarification or add additional context in comments.

1 Comment

please can you explain a bit on this. Runtime is smart enough
11

To add some additional info to the current answers, if you disassemble your class file using:

javap -c TestClass1

You'll get:

Compiled from "TestClass1.java"
public class TestClass1 extends java.lang.Object{
static int a;

public TestClass1();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   aconst_null
   1:   astore_1
   2:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   5:   aload_1
   6:   pop
   7:   getstatic   #3; //Field a:I
   10:  invokevirtual   #4; //Method java/io/PrintStream.println:(I)V
   13:  return

static {};
  Code:
   0:   bipush  10
   2:   putstatic   #3; //Field a:I
   5:   return
}

Here you can see that the access to the static field is done in line 7 by the getstatc instruction. Whenever a static field is accessed through code, a corresponding getstatic instruction will be generated in the .class program file.

*static instructions have the particularity that they don't requiere a reference to the object instance to be in the stack prior to calling them (like, for example invokevirtual which does require an object ref in the stack), they resolve the field/method using just an index to the run time constant pool that will be later used to solve the field reference location.

That's a technical reason for the warning "The static field should be accessed in a static way" that some IDEs will throw at you when you write t1.a, because the object instance is unnecessary to resolve the static field.

Comments

2

What is the reason of NullPointerException in a code like that:

  TestClass t = null;
  t.SomeMethod();

If SomeMethod is an instance method it'll do something with standard this reference:

  public void SomeMethod() {
    // Here we'll have a NullPointerException (since "this" is null)
    this.SomeField = ... // <- We usually omit "this" in such a code
  }

Since this is null we'll have NullPointerException. If method, field etc. is static it's guaranteed the absense of this reference, so there'll be no NullPointerException

  public static void SomeStaticMethod() {
    // You can't put "this.SomeField = ..." here, because the method is static
    // Ans since you can't address "this", there's no reason for NullPointerException
    ...
  }

  ...

  TestClass t = null; 
  // Equal to "TestClass.SomeStaticMethod();"
  t.SomeStaticMethod(); // <- "this" is null, but it's not addressed

Comments

2

The static members are shared by all the instances of a class and not reallocated separately to each instance. These are loaded by the classloader moment the class is encountered for the first time. A related SO question

Please do keep in mind these static members do not belong to a specific class instance. More info here. I have included a small code snippet for reference:

@NotThreadSafe
public class Test {

  // For all practical purpuose the following block will be only executed once at class load time.
  static {
   System.out.println("Loaded by the classloader : " + Test.class.getClassLoader());
  }

  // Keeps track of created instances.
  static int instanceCount;


  // A simple constructor that increments instance count.
  public Test(){
   Test.instanceCount++;
   System.out.println("instance number : " + instanceCount);
  }

  public static void main(String[] args) {
   System.out.println("Instaintiating objects");
   new Test(); new Test();
  }

  // Where would you expect this line to get printed? 
  // i.e last statement on the console or somewhere in the middle :)
  static {
    System.out.println("It should be printed at the end or would it?");
   }
 }

2 Comments

I mentioned something in bold letters...please read the question before answering if possible. but +1 for clear example of Static concept.
my bad.... should be more careful when answering a question.
1

t1.a is equivalent to TestClass1.a in this case, since a is a static member (not an instance member). The compiler looks at the declaration of t1 to see what type it is, and then just treats it as if you had used the type name. The value of t1 is never checked. (But if it were a method call, like method(args).a, I think the method would be called. But the return value would be thrown away, and never checked.) (Edit: I've verified that method(args) is called, but no exception is thrown if the function result is null.)

Comments

0

Any Static member can be accessed by Directly class name as TestClass1.a no need of instance for it

  System.out.println(TestClass1 .a);

output: 10

1 Comment

I mentioned something in bold letters...please read the question before answering if possible.
0

Since a is static compiler converts it to TestClass1.a. For non-static variables it would throw NullPointerException.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.