473,386 Members | 1,621 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,386 developers and data experts.

Class Initializers

13,262 8TB
Inspiration

Inspired by a post by Jos in the Java forum, I have put together a little article on class initializers.
Initializers are indeed underutilized by most Java programmers. Once the Java programmer knows about the constructor he/she feels they have found a good place to put code that must be run before an object is created and sometimes don't try to look for more places to put pre-object creation code. The other places to put pre-object creation code are initializers.

There are two types of initializers that can be used in classes. Static initializers and instance initializers.


Static initializers.

Static initializers are the first bit of code that is run once when the class is being loaded. Since they are static, they are not tied to any particular instance but rather are shared among all objects of their class. An instance initializer block is thus executed only once (during class loading). After that, creation of objects in the program do not trigger execution of the static initializer block again. Another consequence of being static is that you can only use static initializers to initialize static variables. This makes sense because these are the only ones available during class loading. Enough chattering, let's dive into an example:

A scenario

The scenario is a Utility class that gives information about products in a database. The class works on a list of all the products in the database by loading them into an arraylist once when the class is loaded and then referring to that arraylist on all subsequent inquiries on products. The exists method for example, does not need to connect to the database but just queries the products ArrayList.

Disclaimer

Please note that this example is for illustration purposes only. This approach is only helpful in a read only database system because if a product is added into the database during this program's execution after the ProductUtils class has been loaded, then that product will not be available in the list of products created at class loading. There are workarounds of course but we digress ...

A static initializer block is simply denoted by a pair of opening and closing braces preceeded by the static keyword with the initialization code placed inside the braces
Expand|Select|Wrap|Line Numbers
  1.  static {
  2. //initialization code goes here.
Here it is in action
Expand|Select|Wrap|Line Numbers
  1. import java.sql.Connection;
  2. import java.sql.DriverManager;
  3. import java.sql.ResultSet;
  4. import java.sql.Statement;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. class ProductUtils {
  8.     static List<Product> products = new ArrayList();
  9.     static {
  10.         try {
  11.             Class.forName("com.mysql.jdbc.Driver");
  12.             Connection con = DriverManager.getConnection("jdbc:mysql://localhost/test","r035198x ", "acomplexpassword");
  13.             Statement st = con.createStatement();
  14.             ResultSet rs = st.executeQuery("select * from Products");
  15.             while(rs.next()) {
  16.                 products.add(new Product(rs.getInt(1), rs.getString(2)));
  17.                 System.out.println("product added");
  18.             }
  19.         }
  20.         catch(Exception e) {
  21.             e.printStackTrace();
  22.         }
  23.  
  24.     }
  25.  
  26.     public static void main(String[] args) {
  27.  
  28.     }
  29.  
  30.     boolean exists (Product product) {
  31.         return products.contains(product);
  32.     }
  33.  
  34. }

Output with a blank main


Running this program with the proper configurations (database created and connector set in the class path correctly) prints product added for each product that is added to the ArrayList of products. Note that I have deliberately left the main method blank but the program connects to the database, loads objects into an arraylist and prints some stuff to the console. The static initializer block is responsible for all this. The main method is innocent.
This should make it clear that an instance of a class is not required for a static initializer block to be executed. Static initializers can be as sophisticated as you wish, just keep in mind that they are executed during class loading and therefore can only access other statics.

The more the merrier?

You can have as many static initializers as you wish in your class. They will be executed in the order that they appear in your code (from the top of the file to the bottom). To make your code easy to read, you should put different tasks in different initializer blocks so that each block performs one logical operation.

Use

Use static initializers to perform operations that must be done once before all objects of a class are created. Doing these operations in a static initializer ensures that they are done once and therefore can speed up your program because it doesn't have to do them again every time an object of that class is created. More specifically, use static initializers for operations that must be done during class loading of that class by the JVM. The example above also contains a common use of static initializers.

A common use

The specs for the Driver interface say
When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager. This means that a user can load and register a driver by calling
Class.forName("foo.bah.Driver")
Database driver writers are being told here that when their drivers are loaded, an object must be created and registered with the driver manager.

The MySQL driver that was used to connect to the database in the example above had to obey this rule. The call to DriverManager.registerDriver() was done in a static initializer of the MySQL driver class which looks something like:
Expand|Select|Wrap|Line Numbers
  1.   static {
  2.         try {
  3.             java.sql.DriverManager.registerDriver(new Driver());
  4.         } catch (java.sql.SQLException E) {
  5.             throw new RuntimeException("Can't register driver!");
  6.         }
  7.  
  8.         if (DEBUG) {
  9.             Debug.trace("ALL");
  10.         }
  11.     }
written by Mark Matthews

This is helpful since loading a driver now just translates to loading the driver class for that driver.

Instance initializers

The difference between static initializers and instance initializers is in the time that they are executed. While static initializers are executed once when a class is loaded, instance initializers are run once before an object is created. This changes matters somewhat. Instance initializers now have access to non-static variables in a class including the this object.
Instance initializers in named classes should be used to initialize instance variables which cannot be initialized using one line of code but should be initialized the same way for all the constructors in that class. Otherwise if the variable should be initialized differently depending on the constructor that was invoked, then it should be initialized in the appropriate constructors.

Expand|Select|Wrap|Line Numbers
  1.  class Cat {
  2.     String name;
  3.     int numOfLegs;
  4.     int numOfEars;
  5.  
  6.     {
  7.         numOfLegs = 2;
  8.         numOfEars = 2;
  9.     }
  10.     Cat(String name) {
  11.         this.name = name;
  12.     }
  13.     public String toString() {
  14.         return name + " has " + numOfLegs + " legs and " + numOfEars + " ears"; 
  15.     }
  16.  
  17.     public static void main(String[] args) {
  18.         System.out.println(new Cat("Mary").toString());
  19.  
  20.     }
  21. }
Here, every cat is initialised with two legs and two ears.

Called before constructors

Instance initializers are always called before a constructor is called (note that the compiler actually generates <init> methods for every constructor in a class and these are the ones called when a constructor is invoked). As with static initializers, multiple initializers are executed in their textual order.

Instance initializers in anonymous classes

When used with anonymous classes, initializers can make cumbersome code more elegant. Generally you want to isolate code that does different operations. Specifically you don't want to mix code that builds a structure (e.g list, map or more exotic structures) with code that manipulates that structure. Suppose you want to build a mapping between Integers and Strings so that 1 maps to “Sunday”, 2 maps to “Monday” etc.
You could build the map as
Expand|Select|Wrap|Line Numbers
  1.  Map<Integer, String> days = new HashMap();
  2. days.put(1, “Sunday”);
  3. days.put(2, “Monday”);
  4. //etc
After this then you start manipulating the map.

If an anonymous class and initializer is used, this can be done as
Expand|Select|Wrap|Line Numbers
  1.  Map<Integer, String> days = new HashMap() {
  2.             {
  3.                          put(1, “Sunday”);
  4.                  put(2, “Monday”);
  5.                          //etc
  6.                }
  7. };
  8.  
The closing }; in the code above clearly marks the end of the creation of the map. Anyone looking over the code can easily switch between checking code that creates the structure and code that manipulates the structure. This can save a few seconds of debugging time depending on the complexity of the initialization. Remember that the HashMap is just an example of a structure that may require several lines of initialization. Other user defined structures can also benefit, perhaps even more, from the same approach depending on the actions that must be done to fully initialize the structure.


Initializers and exceptions

Static initializers cannot throw checked exceptions (it is a compilation error if they do).
An instance variable initializer in a named class can only throw checked exceptions if that exception or one of its supertypes is explicitly declared in the throws clause of each constructor of its class and the class has at least one explicitly defined constructor.(JLS Third Edition[8.3.2]).

Expand|Select|Wrap|Line Numbers
  1.  static {
  2.     if(true) {
  3.         throw new Exception();
  4.     }
  5. }
does not compile.
while
Expand|Select|Wrap|Line Numbers
  1.  public class Sorry {
  2.     String sorry;
  3.     public Sorry() throws Exception{}
  4.         {
  5.         if(true) {
  6.                           throw new Exception();
  7.                     }
  8.     }
  9. }
compiles fine.

Instance variable initializers in anonymous classes, however, are allowed to throw any checked exceptions.
Expand|Select|Wrap|Line Numbers
  1.  import java.io.IOException;
  2. public class Sorry {
  3.     String sorry;
  4.     public Sorry() {}
  5.     public static void main(String[] args) throws IOException{
  6.         System.out.print( new Sorry() {
  7.             {
  8.        if(true) {
  9.                               throw new IOException("Sorry");
  10.                       }
  11.             }
  12.         }.toString());
  13.  
  14.     }
  15.     public String toString() {
  16.         return sorry;
  17.     }
  18.  
  19. }
compiles fine.

In case you are wondering about the name of the class, a friend of mine wrote a Sorry class to apologize 5 000 times to his girlfriend through email and I just stole that class and changed it a bit to suit more serious purposes.

I hope you have now some understanding on initializers and know when to use which one to better your programs in both speed and maintanability.
Dec 3 '07 #1
1 7289
ajos
283 100+
Class initializers

In case you are wondering about the name of the class, a friend of mine wrote a Sorry class to apologies 5 000 times to his girlfriend through email and I just stole that class and changed it a bit to suit more serious purposes.
Hi r035198x,
I was just scanning around this article of yours. Though i didnt read all of the things completely....this one definitely was most funny :) . Funny because, the other day i had to face this very situation and had to say sorry some 200 times in my case(she's less demanding than your friend i guess :)). How the hell did you guys get this idea...coz it took me some time to type all the sorries :(. AnyWays great article. Kudos to you and TSDN.
regards,
ajos
Dec 6 '07 #2

Sign in to post your reply or Sign up for a free account.

Similar topics

4
by: Doug | last post by:
Say I have a class with a constant in it. I also have a variable in that class that I would like to set to that constant as the initialization value. Why doesn't the following work? class...
106
by: A | last post by:
Hi, I have always been taught to use an inialization list for initialising data members of a class. I realize that initialsizing primitives and pointers use an inialization list is exactly the...
6
by: Neil Zanella | last post by:
Hello, I would like to know what the C standards (and in particular the C99 standard) have to say about union initializers with regards to the following code snippet (which compiles fine under...
4
by: John Devereux | last post by:
Hi, gcc has started warning about the lack of inner braces in initializers like :- struct io_descriptor { int number; char* description;
8
by: Pent | last post by:
Hi All, Why is this code valid? How can the static ctor be used? It doesn't act as class ctor at all. struct A { static A() { } }
5
by: Chris | last post by:
Hi, I don't get the difference between a struct and a class ! ok, I know that a struct is a value type, the other a reference type, I understand the technical differences between both, but...
10
by: Ognen Duzlevski | last post by:
Hi, I have a "language definition" file, something along the lines of: page :: name : simple caption : simple function : complex function :: name : simple code : simple
37
by: JohnGoogle | last post by:
Hi, Newbie question... After a recent article in VSJ I had a go at implementing a Fraction class to aid my understanding of operator overloading. After a previous message someone suggested...
3
by: dischdennis | last post by:
Hello List, I would like to make a singleton class in python 2.4.3, I found this pattern in the web: class Singleton: __single = None def __init__( self ): if Singleton.__single: raise...
16
by: shapper | last post by:
Hello, I have the following classes: namespace MyApp.Models { public class Tie { public Count Count { get; set; } public Tie() { this.Count = new Count(); }
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.