Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get static initialization block to run in a java without loading the class

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.

like image 627
randomThought Avatar asked Apr 06 '10 05:04

randomThought


People also ask

What is static initialization block in Java?

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.

Do you know static block in Java when is it getting executed?

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.

When the static block will get loaded and executed?

4. Static blocks execute when the class is loaded into the memory whereas instance blocks execute only when instance of the class is created.

Can we have static block in non static class?

yes we can have a static block in non static class.


1 Answers

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);
}
like image 81
Joachim Sauer Avatar answered Sep 18 '22 13:09

Joachim Sauer