获取静态初始化块以在不加载类的情况下在java中运行

ran*_*ght 8 java static-members static-initializer

我有几个课程,如下所示

public class TrueFalseQuestion implements Question{
    static{
        QuestionFactory.registerType("TrueFalse", "Question");
    }
    public TrueFalseQuestion(){}
}
Run Code Online (Sandbox Code Playgroud)

...

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
    }
}
Run Code Online (Sandbox Code Playgroud)

如何更改TrueFalseQuestion类以便始终运行静态方法,以便在运行main方法时得到1而不是0?我不希望主方法有任何改变.

我实际上是在尝试实现子类向工厂注册的工厂模式,但我已经简化了这个问题的代码.

Boz*_*zho 6

你可以打电话:

Class.forName("yourpackage.TrueFalseQuestion");
Run Code Online (Sandbox Code Playgroud)

这将加载类而不实际触摸它,并将执行静态初始化程序块.


Rob*_*ser 5

TrueFalseQuestion在工厂中注册类,需要调用其静态初始化程序.要执行类的静态初始化程序,TrueFalseQuestion需要引用该类,或者在QuestionFactory.map.size()调用之前需要通过反射加载该类.如果要main保持方法不变,则必须引用它或通过QuestionFactory静态初始值设定项中的反射加载它.我不认为这是一个好主意,但我只是回答你的问题:)如果你不介意QuestionFactory了解所有实现Question它们的类,你可以直接引用它们或通过反射加载它们.就像是:

public class QuestionFactory {

 static final HashMap<String, String > map =  new HashMap<String,String>();

 static {
    this.getClassLoader().loadClass("TrueFalseQuestion");
    this.getClassLoader().loadClass("AnotherTypeOfQuestion"); // etc.
 }

 public static void registerType(String questionName, String ques ) {
     map.put(questionName, ques);
     }
 }
Run Code Online (Sandbox Code Playgroud)

确保map声明和构造在static块之前.如果您不想QuestionFactory了解其实现Question,则必须将它们列在加载的配置文件中QuestionFactory.我能想到的唯一其他(可能是疯狂的)方法是查看实现的类的整个类路径Question:)如果所有实现的类Question都需要属于同一个包,那可能会更好- 注意:我不赞同这个解决方案;)

我不认为在QuestionFactory静态初始化程序中执行任何操作的原因是因为类TrueFalseQuestion具有自己的静态初始化程序QuestionFactory,这些接收程序在此时是一个未完全构造的对象,这只是在寻找麻烦.有一个配置文件只是列出你想QuestionFactory知道如何构建的类,然后在它的构造函数中注册它们是一个很好的解决方案,但它将意味着改变你的main方法.