• 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
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Static Initialisers

 
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All,

A few idiot questions about static initialisers:

1. If you have one, at what point does the static initialisation code run? Before or after the constructor? or is it JVM dependent?

2. Can you run any valid java code in a static initialiser? or is it confined to initialising static variables? Does the compiler impose any restrictions on the code you can use in a static initialiser?

3. If you can run any code what's the difference between a static initialiser and a no-arg constructor?

Thanks in advance for any inputs.

Regards,
Phil.
 
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Phil,

Static initializers run when the class is loaded, which is before any objects of the class are constructed. Static initializers run even if no instances of the class ar ever constructed. No-arg constructors construct objects, while static initializers in a sense construct the class -- they do setup that all instances of a class can depend on having occurred just once, ahead of time.

There are no restrictions on what legal Java code can go in a static initializer; anything you can dream up is fair game.
 
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Phil Hopgood:
3. If you can run any code what's the difference between a static initialiser and a no-arg constructor?


As said by Ernest, a static initializer is run before any instance is even created, and can therefore be used for some class-wide initialization. Good examples are loading native libraries or registering JDBC drivers.

Now as for the need for non-static initializers: I have never used them, nor do I expect to. Sure they are executed before the constructor, but still after the parent class' constructor. Therefore, everything could go into the constructor as the first part. If that makes your constructor too large, separate the code into private methods that you call at the start of the constructor.

But that's just my opinion.
 
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oooh...

Ok, so a quick question in this vein...

If a static initializer runs when the class is loaded my question is exactly when is the class loaded? Java loads classes when they're necessary if I understand correctly, meaning: a static initializer will run before I instantiate the first object of a class OR perhaps when I first call a static method of the class? Does that make sense?
 
Rob Spoor
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes it does.

I've tested, and my test class only had its static initializers executed if I did one of the following:
- call a static method or field
- create an instance
- called Class.forName() with my class name

One thing that surprised me is that Test.class does NOT load the class, nor did some operations such as calling getName() or even getMethod(), getField(), getClasses() and getInterfaces(). Apparently those do NOT load the class even though the class itself is queried.
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's interesting, Rob -- it's a dark corner I have never explored myself. The JLS actually talks about "class loading and intialization" as two separate things (or two phases of the same thing.) It's the "initialization" part where static initializers get run.

ClassLoader.loadClass() has that optional second boolean argument "resolve" which (despite the name) controls whether the loaded class will be initialized or not. Initialization usually happens immediately when a class is loaded, but apparently there are real cases where a class will be loaded but not immediately initialized.
 
Leroy J Brown
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Wow, that's interesting. I was just looking recently at all the ways it is possible to get the RTTI. Using .class seemed weird enough to me considering classes aren't inheriting a .class field from object, only the .getClass() method. So its one of those slight of hand behind the scenes moves.

It's interesting that we can learn if the .class call (or anything else for that matter) initializes or just loads the class by whether the static initializer is called.
 
Marshal
Posts: 28193
95
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Rob Prime:
Now as for the need for non-static initializers: I have never used them, nor do I expect to.

Here's an example of an instance initializer which I have used:
What? Where is it, you say? Well, that code creates an anonymous subclass of HashMap. But it doesn't override any of HashMap's methods. All it does is to include an instance initializer which adds three entries to the map. (Remember that anonymous subclasses can't have constructors.) End result: a Map containing three pre-filled entries.

Okay, that's just showing off really. There are other ways to do that.
[ July 26, 2008: Message edited by: Paul Clapham ]
 
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Rob Prime:
Now as for the need for non-static initializers: I have never used them, nor do I expect to.



I've hardly ever used non-static init blocks (appropriately) myself, but what about the following scenario:

 
Bartender
Posts: 4179
22
IntelliJ IDE Python Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In cases like that I have always factored the code into a private method that all the constructors call, since it is more clear what is happening:



Originally posted by Jelle Klap:


I've hardly ever used non-static init blocks (appropriately) myself, but what about the following scenario:

 
Jelle Klap
Bartender
Posts: 1952
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Steve Luke:
In cases like that I have always factored the code into a private method that all the constructors call, since it is more clear what is happening:




I suppose that is the most common approach, and while calling a private method from every constructor certainly is expressive -huge nitpick in 3,2,1- it's still a form of code duplication. Also, if a new constructor is ever added there is ofcourse the risk that the private method call will be unwittingly omitted. Both of these issues (if you choose to call them that) can be avoided by using an init block instead.

You called the private method approach clearer than the init block approach. While I guess that doesn't mean you think an init block is inherently unclear, I believe its use can be equally clear.
It's ceratainly true that init blocks can be scattered (almost arbitrarily) throughout the code, so a development team should -as part of their coding standard- agree to follow ceratain guidelines. For instance, declaration of an init block should immediately preceed the declaration of any constructor, be limited to a single occurence, and be clearly documented. Any developer should be able to spot and recognize an init block and know the implications associated with its declaration.
[ July 27, 2008: Message edited by: Jelle Klap ]
 
Rob Spoor
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Tristan Rouse:
Wow, that's interesting. I was just looking recently at all the ways it is possible to get the RTTI. Using .class seemed weird enough to me considering classes aren't inheriting a .class field from object, only the .getClass() method. So its one of those slight of hand behind the scenes moves.


.class is not a method or field, but part of the syntax. It returns the Class object of the type you call it on. For instance, Object.class == new Object().getClass().

Consider it a shortcut to get a reference to a Class object without having to resort to a) creating an unnecessary instance, or b) calling Class.forName and having to deal with exceptions while it's unnecessary because you know the class is there - the compiler enforces it.

As an added bonus, Object.class returns Class<Object> whereas Class.forName returns Class<?> for all classes.
 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'll through my thoughts and what I've done before into the mix here as well...


As far as static initializers, if I'm not mistaken, JDBC drivers use them to register with the DriverManager. This is where I've used them as well. Instead of having to explicitly call a method on a specific class to register with something, I can make a String[] holding the names of the classes I want to register (could be read in from a file), and do a Class.forName() on each one. It makes your code more dynamic, and somewhat easier because the user doesn't have to worry about calling the register method.

Non-static initializers are actually quite useful partly for one of the reasons mentioned above. If you put shared constructor code into a non-static initalizer, it will automatically be called right after the super() is called in the constructor. Yes, you can make a method, and call that in the constructor, but are you or anyone who will be modifying the code later going to remember to do that when you add a constructor? I find that forcing something is a lot of times better than trying to remember to do something. Also, setting up member variables is very nice in the non-static initializers (if the variable needs several lines to do this, or a try-catcy). Declare your variable, then right after, your non-static initializer to set it up. I find that it makes for cleaner code than putting the initializers in a seperate method, or in the constructor. Anyone coming back to the code can see exactly what is done to initialize the variable instead of going searching the code for it.

Garrett
 
Phil Hopgood
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Woahhh!

Thanks everyone for your replies I wasn't expecting such a big response! ..... but you left me behind very quickly (bows head in shame), after all I'm just a beginner ....... and now I've got even more questions.

My major queries were answered by Ernest and Rob, so thanks guys. The ensuing discussion was very interesting but a bit over my head, which is good, don't get me wrong, gives me something to reach for and more depth, but I'm afraid I've got more idiot questions now:

1. What is RTTI? JLS I guess is Java Language Spec?

2. What is a non-static initialiser? I've not come across that yet, unless you're all referring to something I know by another name. From Rob's initial response am I right in saying that it's code that runs when a class is instantiated but before that instance's constructor? If so what is the syntax? Am I right in believing that a non-static initialiser is not the same as a no-arg constructor?

3. I take it all the static initialisers in an inheritance tree run in turn from Object downward as soon as a reference to that class is declared [also ref question 5] (or a static method called or the like)? or is it the other way around?

4. What happens when an object of this class is created? Does the non-static initialiser followed by the appropriate constructor at each hierarchical level in turn (upward or downward) then run? I'm sure this is an idiot question but please bare with me.

5.

ClassLoader.loadClass() has that optional second boolean argument "resolve" which (despite the name) controls whether the loaded class will be initialized or not. Initialization usually happens immediately when a class is loaded, but apparently there are real cases where a class will be loaded but not immediately initialized.



Given the discussion in the preceding posts, how do you know if the static initialiser for a given class has run then?

6. Where do the static variables live? I'm guessing somewhere on the heap.

Sorry if these questions seem a bit basic but I've just got to ask 'em.

Also I'm glad you launched into this discussion (if a bit daunting at first) because it just brings me on that little bit faster ..... once I think about it a bit.

Regards and happy Monday,
Phil
[ July 28, 2008: Message edited by: Phil Hopgood ]
 
Bartender
Posts: 10336
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


1. What is RTTI? JLS I guess is Java Language Spec?


Run Time Type Identification. It is a technique Java uses that means you can write code that changes behaviour depending on the type of object at run time. The most obvious use of this is method overloading, where you write a method with the same name but different parameter types. e.g. :

Now which method is called at run time depends on the type of the parameter.

The most useful mechanism this gives us is the ability to write code for "base" types (e.g. an abstract class or an interface) but have some of our code behave differently depending on the implementaion of this abstract type.
[ July 28, 2008: Message edited by: Paul Sturrock ]
 
Phil Hopgood
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for that Paul.

Now you've spelt out the acronym (don't you just hate TLA's ..... larf .... please) and reminded me I can see what's meant - polymorphism in action eh!

After a bit of research I think I've answered almost all my other questions now. I know I should have searched JavaRanch's forums before - it's in the notes d@mn it! - and read a number of previous similar posts on the subject of initialisers, constructors and the like. This has helped me greatly to at least have a model in my mind on which to build a deeper understanding.

I bet you guys get fed up of answering the same old questions when the answers are there on the forum somewhere if only us newbies would take the trouble to look for them. Sorry. I'll search first, ask after in future.

Can I just trouble you to confirm or not that I've now got it straight in my head please?

If I've got a class that's got a number of levels of parentage each level having both static and non static initialisers and constructors:



have I got the order of events correct? or do all the static variables get established at all levels first and then their respective initialisers run?

Am I right that it propagates on up to Object like that?

If any other newbie is following this thread I found a great answer to my question 6 Where do the static variables live? here

Thanks for all your help guys.
Regards,
Phil

[ July 29, 2008: Message edited by: Phil Hopgood ]
[ July 29, 2008: Message edited by: Phil Hopgood ]
 
Steve Luke
Bartender
Posts: 4179
22
IntelliJ IDE Python Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The best way to test what methods are called when is by putting System.out.println() statements in each block to see what order they get executed in. It sometimes is an eye-opening experience to do so...
 
Ernest Friedman-Hill
author and iconoclast
Posts: 24207
46
Mac OS X Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Phil --

Yes, it looks like you've got it!
 
Phil Hopgood
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
YeeeHaaaaa

Steve, I'm gonna try what you suggested on the above example .... should be interesting...... I gotta get out more.

Thanks guys,
Regards,
Phil
 
reply
    Bookmark Topic Watch Topic
  • New Topic