Подтвердить что ты не робот

Синглтон и исключение

Каков наилучший способ создания одноэлементного класса, который может генерировать исключение?

Здесь у меня есть Singleton (с использованием метода Билла Пью, задокументированного в Wiki для Singleton).

    private static class SingletonObjectFactoryHolder{
    //1  
        private static final ObjectFactory INSTANCE = new ObjectFactory();
    }

    private ObjectFactory() throws Exception{
    //2
            //create the factory
    }


    public static ObjectFactory getInstance(){
    //3
        return SingletonObjectFactoryHolder.INSTANCE;
    }

Если исключение выбрано в 2, я хотел бы распространить его на вызывающего. Однако я не могу исключить исключение из строки 1.

Итак, мой единственный вариант - вернуть нулевой объект, если объект singleton был создан неправильно?

Спасибо

P.S Я понимаю, что этот Singleton может сломаться, если он загружен через разные загрузчики классов или если он загружен рефлексивно, но он достаточно хорош для моей цели.

//UPDATE

Мне любопытно, не могу ли я изменить порядок моего дизайна, как показано ниже, для исключения исключений?

Кроме того, мне не нужна синхронизация (загрузчик классов гарантирует, что статический внутренний класс будет загружаться только один раз и только когда вызывается getInstance()). Таким образом, поточно-безопасный и лениво-экземпляр?

 private static class SingletonObjectFactoryHolder{
        //1  
           public static ObjectFactory getInstance() throws Exception{
         return new ObjectFactory();
           }
 }

 private ObjectFactory() throws Exception{
        //2
        //create the factory
 }


 public static ObjectFactory getInstance(){
        //3
    return SingletonObjectFactoryHolder.getInstance();
 }

Еще раз спасибо.

4b9b3361

Ответ 1

Используйте статический инициализатор и перезапустите Exception как ExceptionInInitializerError. Нажмите ссылку, чтобы прочитать Javadoc, вы увидите, что она подходит именно для этого конкретного функционального требования: обработка исключений во время статической инициализации. Синглтон на самом деле не меньше или больше, чем статически и лениво инициализированный глобальный объект.

private static class SingletonObjectFactoryHolder{
    private static final ObjectFactory INSTANCE;
    static {
        try {
            INSTANCE = new ObjectFactory();
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
}

Нет необходимости в двойной проверенной блокировке идиомы, которая считается анти-шаблоном и в некоторых случаях даже небезопасной.

Ответ 2

Просто не бросайте исключение из конструктора объекта. Вы можете предоставить метод init () и отбросить свое исключение, если это необходимо.

Ответ 3

Вы можете проверить нуль INSTANCE внутри getInstance и лениво инициализировать его. Но обычно лучше всего, если конструкторы не бросают, если вы можете сделать конструктор более безопасным, что, вероятно, будет лучше.

Ответ 4

Я согласен с Арне Бурмейстером, код для этого будет выглядеть так:

private static class SingletonObjectFactoryHolder
{
    private static ObjectFactory INSTANCE;


    private ObjectFactory() 
    {

    }

    public static String getInstance() throws Exception
    {
      return (INSTANCE == null) ? (INSTANCE = new ObjectFactory()) : INSTANCE; 
     // A ternary operator might not be the best fit if you need to throw an exception, but I think it looks nicer than the if(INSTANCE==null){} else{} for lazy instantiation.
    }

}