ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Understanding the Interplay Between Utility Classes and Static Initialization
Pages: 1, 2

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.