2017-02-04 9 views
1

Я установил объект private static properties для загрузки в некоторой конфигурации для моего заводского класса в конструкторе фабричного класса.Закрытая переменная статического свойства приводит к исключению нулевого указателя

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 

Затем, если я изменяю объект свойств на нестатический объект, проблема решена. Но меня все еще смущает причина, почему это произойдет и как это можно решить таким образом.

+0

Ну, исключение говорит, что проблема находится в * testFindOrder *, и вы показываете нам * testPageQuery *. Как нам помочь? – CKing

ответ

1

статические инициализаторы выполняются сверху вниз. Таким образом, статическое поле factory инициализируется при загрузке класса BussinessServiceFactory. Этот статический инициализатор вызывает конструктор для BussinessServiceFactory, и поэтому поэтому в конечном итоге загружает ссылку на статическое поле bsConfig. Это поле еще не инициализировано на этом этапе, поскольку мы все еще находимся в статическом блоке инициализатора для поля factory. Следовательно, исключение NullPointerException.

Fix это либо 1) изменение порядка bsConfig поля, чтобы быть выше factory области, или еще лучше, не имеет такую ​​внутриполевому зависимости, делая bsConfig поле поле экземпляра (который является то, что вы сделали, чтобы исправить это, и я считаю, что это лучший способ исправить такую ​​проблему).

см. http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4 для получения дополнительной информации о порядке статической инициализации.

добавление: Стекловатка раскрывает источник вашей проблемы. clinit в stacktrace обозначает cl ass init, и поэтому вы можете сказать, что проблема заключается в загрузке класса.

+0

Большое вам спасибо, ваш ответ очень полезен! –