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.
A Static Initialization Block in Java is a block that runs before the main( ) method in Java. Java does not care if this block is written after the main( ) method or before the main( ) method, it will be executed before the main method( ) regardless.
Static blocks in Java are executed automatically when the class is loaded in memory. Static blocks are executed before the main() method. Static blocks are executed only once as the class file is loaded to memory.
4. Static blocks execute when the class is loaded into the memory whereas instance blocks execute only when instance of the class is created.
yes we can have a static block in non static class.
The static initializer for the class can't be executed if the class is never loaded.
So you either need to load all the correct classes (which will be hard, since you don't know them all at compile time) or get rid of the requirement for the static initializer.
One way to do the latter is to use the ServiceLoader
.
With the ServiceLoader
you simply put a file in META-INF/services/package.Question
and list all implementations. You can have multiple such files, one per .jar file. This way you can easily ship additional Question
implementations separate from your main program.
In the QuestionFactory
you can then simply use ServiceLodaer.load(Question.class)
to get a ServiceLoader
, which implements Iterable<Question>
and can be used like this:
for (Question q : ServiceLoader.load(Question.class)) {
System.out.println(q);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With