I have a few classes as shown here
public class TrueFalseQuestion implements Question{
static{
QuestionFactory.registerType("TrueFalse", "Question");
}
public TrueFalseQuestion(){}
}
...
public class QuestionFactory {
static final HashMap<String, String > map = new HashMap<String,String>();
public static void registerType(String questionName, String ques ) {
map.put(questionName, ques);
}
}
public class FactoryTester {
public static void main(String[] args) {
System.out.println(QuestionFactory.map.size());
// This prints 0. I want it to print 1
}
}
How can I change TrueFalseQuestion
class so that the static method is always run so that I get 1 instead of 0 when I run my main method? I do not want any change in the main method.
I am actually trying to implement the factory patterns where the subclasses register with the factory but i have simplified the code for this question.
To register the
TrueFalseQuestion
class with the factory, its static initializer needs to be called. To execute the static initializer of theTrueFalseQuestion
class, the class needs to either be referenced or it needs to be loaded by reflection beforeQuestionFactory.map.size()
is called. If you want to leave themain
method untouched, you have to reference it or load it by reflection in theQuestionFactory
static initializer. I don't think this is a good idea, but I'll just answer your question :) If you don't mind theQuestionFactory
knowing about all classes that implementQuestion
to construct them, you can just reference them directly or load them through reflection. Something like:Make sure
map
's declaration and construction is before thestatic
block. If you don't wantQuestionFactory
to have any knowledge of the implementations ofQuestion
, you'll have to list them in a configuration file that gets loaded byQuestionFactory
. The only other (possibly insane) way I could think to do it, would be to look through the entire classpath for classes that implementQuestion
:) That might work better if all classes that implementedQuestion
were required to belong to the same package -- NOTE: I am not endorsing this solution ;)The reason I don't think doing any of this in the
QuestionFactory
static initializer is because classes likeTrueFalseQuestion
have their own static initializer that calls intoQuestionFactory
, which at that point is an incompletely constructed object, which is just asking for trouble. Having a configuration file that simply lists the classes that you wantQuestionFactory
to know how to construct, then registering them in its constructor is a fine solution, but it would mean changing yourmain
method.