1

I have set a private static properties object to load in some configuration for my factory class in the constructor of factory 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);
        }
    }
}

However, when I initialize the class, it throws NullPointerException.

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

Then if I change the properties object into non-static object, the problem is solved. But I am still confused by the reason why would this happen and how it could be solved in this way.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Wenjie Li
  • 13
  • 4

1 Answers1

1

static initializers are done topdown. So the static field factory is initialized when the class BussinessServiceFactory is loaded. This static initializer calls the constructor for BussinessServiceFactory, and so therefore, eventually, loads a reference to the static field bsConfig. This field is not yet initialized at this point, since we are still in the static initializer block for the factory field. Hence, the NullPointerException.

Fix this either 1) reordering the bsConfig field to be above the factory field, or better yet, don't have this interfield dependency by making the bsConfig field an instance field (which is what you did to fix it, and i believe is the best way to fix such an issue).

see http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 for details about order of static initialization.

addendum: the stacktrace reveals the source of your problem. The clinit in the stacktrace stands for class init, and therefore, you can tell that the issue is loading of a class.

Chii
  • 14,540
  • 3
  • 37
  • 44