ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


Understanding the Interplay Between Utility Classes and Static Initialization Understanding the Interplay Between Utility Classes and Static Initialization

by Satya Komatineni
09/15/2004

Java is an OO language, which means much of the functionality of a Java application is encapsulated into cohesive classes that can be instantiated and acted upon. Nevertheless, once in a while you end up with some functions that are applicable to more than one class. These functions don't really belong to any particular class, but to a sub-system or a package. Although one can express this grouping as a class by itself (represented by interfaces), it is just simpler to collect them as static functions in a class, when one doesn't need the sophistication of service-centric approach for these methods. For example, I have a class called ServletUtils (see Example 1 below).

One characteristic of static functions is that they are stateless, although for efficiency they may depend on some static variables. When these static variables are introduced or utilized, you need to know the class initialization rules laid out by the language. Although these rules are fairly intuitive, it is beneficial to know them in some depth, as static initialization involves side effects. This article is about what these side effects are and how to minimize them through a pattern called Static Resource Holder. With this in mind, I want to first review the basics of static initialization rules. For a complete treatment of the rules, refer to the Java language specification links at the end of the article.

Example 1. ServletUtils

public class ServletUtils
{
   static public void 
   writeOutAsJavaScript(PrintWriter out,
                        StringBuffer javaScript);
   
   static public String 
   convertToHtmlLines(String inString);
   
   static public Map 
   parseQueryString(String httpQueryString);
   
   static public Map 
   getParameters(HttpServletRequest request);
   
   static public String
   getSusbstitutedURL(String encodedString,
                      Map arguments);
   
   //.. so on and so forth
}

Simplified Rules of Static Initialization

  1. A class is initialized before any of its members are accessed. The accessed members can include class variables and static functions.

  2. Before a class is initialized, its superclass is initialized first.

  3. You can use static blocks to initialize static variables. Java not only allows static variables, but also blocks of code that are declared just like variables. These are nameless blocks of code that appear alongside the variables.

  4. Static variables and static blocks are executed in the order they appear in source code (so-called textual order).

  5. A class is initialized before any of its instances can exist.

Rules of Static Blocks

  1. Static blocks cannot return. They are simply nameless blocks of code that execute in the order they are specified.

  2. Static blocks cannot throw checked exceptions. This is somewhat expected as well, since they're called by the internals of the JVM. With all of the exceptions possible in arbitrary blocks of code, the JVM could not possibly meaningfully declare them all and warn about them through checked exceptions.

  3. Nevertheless, static blocks can throw runtime exceptions. This also should be expected, because any piece of code in Java could result in a runtime exception, such as NullPointerException, ArrayIndexOutOfBoundsException, etc.

  4. Being static in nature, these static blocks of code cannot refer to this or super because at the time the static block is executed, there is not yet an instance of these classes.

Static Initialization Surprise

While reviewing the static initialization behavior, I ran into an interesting piece of code involving name resolution and a static variable. Under this scenario, accessing a static variable of a class through one of its subclass's namespaces will not initialize the subclass (as one might rightly or wrongly expect), but instead will only initialize the superclass.

Consider the following superclass with a static variable defined in it. There is no magic in this class: a static variable and a static block, perhaps completely unrelated to each other.

class superClass
{
   public static int i=10;
   static 
   {
      System.out.println("Super class initialized");
   }
}

In addition to demonstrating the oddity that will be revealed shortly, this code also demonstrates the basic syntax of a static block of code. Notice how bare it is in its structure, only demarcated by the static keyword. Also notice that there are no returns in the code block, nor any exceptions. Nevertheless, it is perfectly acceptable to throw runtime exceptions.

Now let us try to access that static variable i and see what happens. To test this out, let me define a simple Test class with a main in it that makes use of the variable i.

public class Test
{
    public static void main(String[] args)
    {
    	System.out.println("Accessing static i:" + superClass.i);
    }
}

When executed, the Test class will produce the following output:

Super class initialized
Accessing static i:10

See how the intended output ("Accessing static i:10") shows up after the Super class initialized print statement? This is a typical behavior of the static initialization--Side Effects 101 stuff. Now let me introduce a subclass and access the same static variable through the scope of the subclass, and see the nature of the print statements.

class subClass extends superClass
{
   static
   {
      System.out.println("sub class initialized");
   }
}

public class Test
{
    public static void main(String[] args)
    {
    	System.out.println("Accessing static i:" + subClass.i);
    }
}

Notice how in the main method I am accessing the static variable i via the subclass and not the superclass (to which it actually belongs). This code, when executed, produces the following lines.

Super class initialized
Accessing static i:10

As you can see, this test code does not initialize the child, although the variable is invoked through its namespace.

The Shock Effect of Static Access

So much for the digression; let me return to the main topic of the article, namely the side effects of static initialization. Static access happens when you access a static variable or invoke a static method, or instantiate one of its type. This will automatically trigger a lot of things. First, the class containing the variable or method is initialized, if it hasn't been already. This implies that all of the static fields will be initialized. If this initialization involves any newing of classes, then a lot of constructors are called. This is followed by the execution of whatever static blocks are there for that class. In fact, the side effects are further compounded when the class in case is inheriting other classes, as those classes get initialized first.

Consider the following static class, with three static functions: sf1, sf2, and sf3.

public class sc
{
   public static void sf1(){ .... }
   public static void sf2()
   {
   	SomeResource r = new SomeResource();
	r.primeTheResource();
	doSomething(r,"otherstuff");
   }
   public static void sf3(){ .... }
}

From the three functions, I have provided the body for one of the functions, sf2. This function acquires a resource, and primes the resource before doing something with it. If the resource r is immutable after being initialized, it is possible to optimize the code by creating it once and using it again and again. Static initialization immediately suggests itself as a possible solution. This idea leads to the following code:

public class sc
{
   private static SomeResource r = null;
   static
   {
      SomeResource r = new SomeResource();
      r.primeTheResource();
   }
   public static void sf1();
   public static void sf2() 
         { doSomething(r, "otherstuff");
   public static void sf3();
}

See how a static block is used to initialize the resource r? Because of the static block, this initialization takes place only once. That leaves the function sf2 to just use the resource, instead of initializing it every time. So far, so good. When I started using static initialization to solve such problems, my work would have stopped here. But on further examination, there are some issues with this code.

Suppose there is a rule that primeTheResource() cannot be called unless the system is initialized. This means that there is a point in the application initialization process before which r.primeTheResource() is invalid. While writing this class, I am quite confident that sf2() is always called after the application initialization. But the static class sc is designed to be a utility class. What if the person writing the application initialization process sees that there is a very useful function called sf1 and decides to use it as part of the application initialization process?

Calling sf1() as part of initialization invokes r.primeTheResource(), which expects the initialization to be complete before being valid. Such unwanted dependency occurred because I broke the class cohesion rule, which states that a class is not a general collection of methods but rather a cohesive, related module. The cohesion rule is apt and usually correct when I am designing instance classes. But since the class sc is a utility class, it is a pain to design n utility classes for n purposes.

Solution: The Static Resource Holder Pattern

The unwanted dependency demonstrated so far can be broken by using a holder class for that can hold the single resource r. Here is an example:

public class sc
{
   public static void sf1();
   public static void sf2() 
      { doSomething(ResourceHolder.r, "otherstuff");
   public static void sf3();
}

The static class no longer holds a reference to the static variable r; instead, it borrows it from its holder class. Here is the ResourceHolder class that hosts the static variable r and initializes it at its first use.

public class ResourceHolder
{
   public static SomeResource r = null;
   static
   {
      SomeResource r = new SomeResource();
      r.primeTheResource();
   }
}

A Real-World Example

So far I have talked about abstract examples to show dependencies and the Static Resource Holder pattern. Now I would like to show a concrete example of how the Resource Holder pattern can be used. In this example, I want to take a parameterized URL string and then replace the parameters with their actual values to get the final URL. The parameterized URL would look something like this:

/{aspireContext}/display/url=ShowPage1URL&arg1={arg1}&arg2={arg2.encode}

If aspireContext is akc, arg1 is 15, and arg2 is abc xyz, then the expanded string will look like this:

/akc/display/url=ShowPage1URL&arg1=15&arg2=abc+xyz

Now let me consider the static method that does the substitution:

public static String getSubstitutedURL(String urlString, 
                           Map urlArgs)
  {
   Map map = new HashMap();

   //Shell dictionary
   IDictionary paramDictionary = new MapDictionary(map);

   //Search context dictionary first
   paramDictionary.addChild(
       ContextDictionaryHolder.s_contextDictionary);

   //Search url arguments next
   paramDictionary.addChild(new MapDictionary(urlArgs));

   //Search application configuration last
   paramDictionary.addChild(ConfigDictionary.self);

   //Replace heeding the rules of url encoding
   return SubstitutorUtils.urlencodeSubstitute(urlString,
                                               paramDictionary);
  }

The method uses hierarchical dictionaries to resolve parameter names to their values. Importantly for this discussion, it uses a cached dictionary called context dictionary that is always the same for a given web context. Instead of maintaining a static variable for the context map that needs to be prepared once for the application inside the class, the solution uses a ContextDictionaryHolder class to do the acquiring and initializing. The code for the ContextDictionaryHolder is as follows:

class ContextDictionaryHolder
{
   public static IDictionary s_contextDictionary = null;
   static
   {
      String aspireContext = ServletUtils.getWebApplicationContext();
      if (aspireContext == null) aspireContext = "";
      HashMap m = new HashMap();
      m.put("aspirecontext",aspireContext);
      
      //Place other context related information into this dictionary
      .....
      
      //Finally hold that in a dictionary
      s_contextDictionary = new MapDictionary(m);
   }//end of function
}//end of class

The static variable s_contextDictionary is initialized using a static block and the side effects are localized to only this class. The servlet API might provide other solutions to the context problem; nevertheless, this code demonstrates how static resource holders can be used in real situations.

Conclusion

Based on the discussion, a Java class with static blocks and a lot of static functions should flag a warning, since invocation of these functions may wrongly trigger side effects. This means that one has to pay special attention to side effects similar to this when writing static blocks. I'm not advocating converting all of your static blocks to use static resource holders, but look to see if a given situation necessitates a static resource holder. When you do see unwanted side effects, you can use Static Resource Holders to eliminate those unwanted side effects.

References

Satya Komatineni is the CTO at Indent, Inc. and the author of Aspire, an open source web development RAD tool for J2EE/XML.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.