私有静态属性变量导致空指针异常

时间:2017-02-04 16:27:48

标签: java nullpointerexception static-initialization

我已经在工厂类的构造函数中为工厂类的某些配置设置了一个私有静态属性对象。

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);
        }
    }
}

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

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

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

1 个答案:

答案 0 :(得分:1)

静态初始化器自上而下完成。因此,在加载类factory时会初始化静态字段BussinessServiceFactory。此静态初始值设定项调用BussinessServiceFactory的构造函数,因此最终加载对静态字段bsConfig的引用。此时此字段尚未初始化,因为我们仍然在factory字段的静态初始化程序块中。因此,NullPointerException。

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

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

附录: stacktrace揭示了你的问题的根源。 stacktrace中的clinit代表 cl ass init ,因此,您可以判断问题是加载了一个类。