Let’s say that you are using a type-safe enumeration pattern to reference a list of protocols. Your protocol object might have a reference to a ProtocolHandler class which a client would use to load on demand using reflection.
Look at the following code see if you can identify a possible trouble spot.
public class Protocol {
private Class protocolHandlerClass;
public static final Protocol TIBCO = new Protocol(
TibcoProtocolHandler.class);
.
.
.
private Protocol(Class protocolHandlerClass) {
this.protocolHandlerClass = protocolHandlerClass;
}
public Class getProtocolHandlerClass() {
return protocolHandlerClass;
}
}
public class TibcoProtocolHandler {
public static final String SEND_SUBJECT =
loadSendSubjectFromDB();
private static String loadSendSubjectFromDB() {
…
}
}
The first time you reference a class, it will initialize all of it’s static fields. In the case of this example, the TIBCO field would be initialized. The gotcha is that the first time you reference anything on the Protocol class, it will also initialize all the static methods on all of the class objects that it refers to in its static initializers.
When the Protocol object is referenced, it loads all of TibcoProtocolHandler’s static variables (because they are part of the class object). Thus, in this case, the SEND_SUBJECT field would be initialized, which would call the loadSendSubjectFromDB() method. So, the first time you make any reference to Protocol, it will hit the database. Not entirely what you expect when you glance at the Protocol class.
To remedy this, either:
- Don’t use statics in classes that are referenced by their class objects in other classes statics (in this case, don’t put statics in the ProtocolHandler classes)
- Don’t reference class objects in statics, (try making Protocol store strings that represent the classes rather than the class objects themselves)
- Don’t use a static enums (make protocol use a factory method instead of a typesafe enum thus pushing the responsibility of providing the class object out to the client code)