2015-08-02 2 views
4

У меня есть Singleton Logger класс.Использование Singleton in Constructor

public class Logger { 
    public static Logger INSTANCE = new Logger(); 

    private Logger() { 
    ... 
    } 
} 

Я хочу, чтобы мой конструктор создал новый экземпляр. Так что мой код выглядит следующим образом:

public class MyClass { 
    public MyClass() { 
    Logger.INSTANCE.log("MyClass created"); 
    ... 
    } 
} 

мне интересно, если это может нарушить статические экземпляры из MyClass. Например, если у меня есть:

public class MyOtherClass { 
    private static MyClass myClass = new MyClass(); 
    ... 
} 

Я боюсь, что это может вызвать проблемы из-за неопределенного порядка инициализации статических переменных. Поэтому, если myClass инициализирован до Logger.INSTANCE, то произойдет сбой конструкции myClass. Есть ли какой-то механизм для предотвращения этого или использует статические переменные в конструкторе по своей сути опасно? Есть ли способ предотвратить создание пользователями статических экземпляров MyClass в таком случае?

+0

Если вы должны использовать одноэлементный шаблон, сам экземпляр не должен быть доступен. Он должен был обернуть метод. – christopher

+0

Обратите внимание, что в этом случае ваша переменная экземпляра должна быть окончательной и частной или защищенной. – chrylis

ответ

4
public class Logger { 
    public static Logger INSTANCE = new Logger(); 

    private Logger() { 
    ... 
    } 
} 

Является ли синтаксический сахар для

public class Logger { 
    public static Logger INSTANCE; 
    static { 
     INSTANCE = new Logger(); 
    } 

    private Logger() { 
    ... 
    } 
} 

Статический блок устанавливает статические члены класса и is guaranteed to run before your class is used.

0

Итак, если myClass инициализирован до Logger.INSTANCE, тогда будет разрушена конструкция myClass.

Вы не можете инициализировать класс до тех пор, пока все классы, от которых он зависит, были инициализированы.

Есть ли какой-нибудь механизм предотвращения этого или использует статические переменные в конструкторе по своей сути опасно?

Вы не можете использовать класс, прежде чем он был инициализирован (если вы не вызовите его в коде инициализации)

Есть ли способ, чтобы запретить пользователям создавать статические экземпляры MyClass в такой дело?

Вы не можете создать экземпляр класса, пока классы, которые он использует, не были инициализированы.

1

Я рекомендую вам обернуть Logger.INSTANCE как в классическом одноточечного:

public class Logger{ 

    private static Logger logger; 

    private Logger(){ 

    } 

    public static Logger getInstance(){ 
    if(logger==null){ 
     logger = new Logger(); 
    } 
    return logger; 
    } 

} 

Таким образом, когда вы будете называть Logger.getInstance() вы никогда не получите null.

Если вам нужна Потокобезопасная синглтон:

public class Logger { 
    private static class Holder { 
     static final Logger INSTANCE = new Logger(); 
    } 

    public static Logger getInstance() { 
     return Holder.INSTANCE; 
    } 
} 

Таким образом, вы никогда не получите null, потому что по умолчанию Logger будет инициализирован перед классом, где он будет использоваться, так как в этом случае будет зависимости другого класса.

+0

Это не потолочный. –

+0

Джордж Симмс, вы правы, добавили потокобезопасное решение. –

+0

Кроме того, ленивая загрузка не является явным требованием. –

0

Не беспокойтесь о нарушении чего-либо, JVM обеспечит правильный порядок строительства. Однако при доступе к моим многим потокам возникает множество экземпляров. Улучшите код, объявляя синглтон окончательным и используя статический метод для доступа:

public class Logger { 
    private static final Logger INSTANCE = new Logger(); 

    private Logger() {} 

    public static Logger getInstance() { 
     return INSTANCE; 
    } 
}