• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Ron McLeod
  • paul wheaton
  • Jeanne Boyarsky
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
  • Himai Minh
Bartenders:

Null Pointer exception when accessing a static instantiated object with in the instance of a class.

 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
I am new to java and have written a small piece of code.

Test.java :





On running Run it gives me a NPE,

[jkalyana@toddler ~]$ javac Test.java
[jkalyana@toddler ~]$ vim Run.java
[jkalyana@toddler ~]$ javac Run.java
[jkalyana@toddler ~]$ java Run
Exception in thread "main" java.lang.ExceptionInInitializerError
at Run.main(Run.java:3)
Caused by: java.lang.NullPointerException
at Test.enter(Test.java:10)
at Test.<init>(Test.java:7)
at Test.<clinit>(Test.java:4)
... 1 more


I had a doubt and changed the Test.java to this,



On moving the declaration of Test below map, it runs,

[jkalyana@toddler ~]$ java Run
Key = dummy1, Value = dummy2

Can anyone tell me why this is so.
 
Ranch Hand
Posts: 213
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Okay, before I explain the flow of the code you have written ... you have to understand the statment below first:

"The order of initialization is statics first, if they haven't already been initialized by a previous object creation, or first invoke of any static method/field of the class. After the initialization for statics complete, only then the turn for non-static object"

Now , follow my explanation

When you run "java Run", the "public static void main" method of class Run invoke. However before this method invoked, class Run loaded and initialized. After this, the "public static void main" method call Test.display() which is a static method of class Test.

Now, do you notice that the display() is the first invoke of static method of the class Test ? So, before these method progress, class Test loaded and initialized. Here start the initialization of class Test, the 1st line is "private static Test instance = new Test();", so it run the constructor "Test()" to create a Test object, and within the constructor it call "enter()", then it execute "map.put("dummy1","dummy2");". However, at this point the map haven't been initialized which is still null, so the NPE thrown. Understand ?

On moving the declaration of Test below map, it runs



If you understand my explanation above, I think you can figure out this yourself. Since the map is the 1st line, it is initialize before Test, which means before the method enter() invoked which access map.



Now, I bring out a good practice which one need to follow is , "In a constructor, you can call superclass method, because superclass surely is completely loaded and initialized. However, in a constructor, one should not (although you can) call method from its own class because it will give a non guarantee behavior where its own class haven't completely initialized"

All The Best, hope my explanation help you to progress.

 
Ranch Hand
Posts: 237
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's because in the first case the map variable is null when you do,

private static Test instance = new Test();

This means this will fail in the enter method,

map.put("dummy1","dummy2"); // error - map is null

When you change the order map isn't null anymore so it works.
 
Kalyana Chakravathy
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Lee Kian Giap wrote:
Now, I bring out a good practice which one need to follow is , "In a constructor, you can call superclass method, because superclass surely is completely loaded and initialized. However, in a constructor, one should not (although you can) call method from its own class because it will give a non guarantee behavior where its own class haven't completely initialized"

All The Best, hope my explanation help you to progress.



Thanks, Now I understood how static declarations are instantiated in the first place. To just check if I understood correctly or not, I made the Test declaration in it non static and removed the getInstance() method and ran it. Now whatever may be the order it prints the values as static objects are instantiated first. Only in the previous case since both were static it followed the order of declaration. I made it like this,



One question, you said it better to always call the superclass from the constructor. By default the default superclass constructor is called. Also the object I want to refer or load when the object is instantiated is within that class and not the super class. So I guess it makes sense to call it from the constructor, or have that piece of code within the constructor itself. How does having superclass solve it. Do you say, I must put the static variable in the superclass ?
 
Lee Kian Giap
Ranch Hand
Posts: 213
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Thanks, Now I understood how static declarations are instantiated in the first place. To just check if I understood correctly or not, I made the Test declaration in it non static and removed the getInstance() method and ran it. Now whatever may be the order it prints the values as static objects are instantiated first. Only in the previous case since both were static it followed the order of declaration



Yes, !!! You get my point !!! This is a very important concept to build strong foundation, cheer !


One question, you said it better to always call the superclass from the constructor.



Sorry, I have to correct your sentence first. I didn't mean it is better to always call the superclass method from constructor. What I try to said is , you can call a superclass method in constructor will not give you such non-guarantee result which you encounter (where you need to arrange your static initialization) because at the point that the subclass calling a superclass method, the object of superclass is completely created (this is handle by compiler implicitly, and that is the reason why you have the keyword super in the subclass)
However, one should always avoid calling the method in the constructor of its own class, which will give you a non-guarantee behavior, this is the important point I trying to bring out !

So, I'm not trying to ask you to call superclass method for your situation by moving things into superclass. I just want to bring out the point that calling superclass method in constructor is SAFE. Hope you understand


By default the default superclass constructor is called. Also the object I want to refer or load when the object is instantiated is within that class and not the super class. So I guess it makes sense to call it from the constructor, or have that piece of code within the constructor itself. How does having superclass solve it. Do you say, I must put the static variable in the superclass ?



For your situation, as explain above, I'm not trying to ask you to call superclass. When one start to call a method of its own class in the constructor, this is the time to rethink what really you are trying to do. As refer to your code, map will be initialize everytime when a new Test object created, this might not be the case you want.

What I can see from your code is you are trying to initialize the map when you need it with a new Test object, my question here is are you actually prefer to initialize the map when class loaded instead of when instantiate a Test object since what I see your map is a static field which share among object.

So, my suggestion is as below by using static initialization


 
Marshal
Posts: 80736
485
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

kalyana cj wrote:. . . By default the default superclass constructor is called. . .

No, by default a superclass no-arguments constructor is sought. It is invoked if it exists. If not, you must provide a super( . . . ); statement.
 
reply
    Bookmark Topic Watch Topic
  • New Topic