private static 属性变量导致空指针异常

Private static property variable leads to null pointer exception

我在工厂 class 的构造函数中设置了私有静态属性对象以加载我的工厂 class 的一些配置。

public class BussinessServiceFactory {
    private static final BussinessServiceFactory factory = new BussinessServiceFactory();
    public static BussinessServiceFactory createBussinessServiceFactory(){
        return factory;
    }
    private BussinessServiceFactory(){
        InputStream in = BussinessServiceFactory.class.getClassLoader().getResourceAsStream("factory/bussinessservice.properties");
        try {
            bsConfig.load(in);
        } catch (IOException exception) {
            // TODO Auto-generated catch block
            throw new RuntimeException(exception);
        }
    }
    private static Properties bsConfig = new Properties();
    public <T> T createBussinessService(Class<T> clazz){
        try {
            String clazzName = clazz.getSimpleName();
            String name = bsConfig.getProperty(clazzName);
            return (T) Class.forName(name).newInstance();
        } catch (InstantiationException | IllegalAccessException
                | ClassNotFoundException exception) {
            throw new RuntimeException(exception);
        }
    }
}

但是,当我初始化 class 时,它抛出 NullPointerException

java.lang.NullPointerException
    at factory.BussinessServiceFactory.<init>(BussinessServiceFactory.java:15)
    at factory.BussinessServiceFactory.<clinit>(BussinessServiceFactory.java:8)
    ... 24 more

那如果我把属性对象改成非静态对象,问题就解决了。但是我仍然对为什么会发生这种情况以及如何以这种方式解决它感到困惑。

静态初始化程序是自上而下完成的。因此静态字段 factory 在 class BussinessServiceFactory 加载时被初始化。此静态初始化程序调用 BussinessServiceFactory 的构造函数,因此最终加载对静态字段 bsConfig 的引用。该字段此时尚未初始化,因为我们仍在 factory 字段的静态初始化程序块中。因此,NullPointerException。

解决此问题 1) 将 bsConfig 字段重新排序到 factory 字段上方,或者更好的是,通过使 bsConfig 字段成为实例字段(这是您修复它的方法,我相信这是解决此类问题的最佳方法)。

有关静态初始化顺序的详细信息,请参阅 http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4

附录: 堆栈跟踪揭示了问题的根源。堆栈跟踪中的 clinit 代表 class init,因此,您可以看出问题是加载 class.