Конструктор в классе статических методов - PullRequest
4 голосов
/ 12 января 2012

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

public class MyClass
{
    private static final String KEYS = "ABC";
    private static final String[] DATA = {"AAA", "BBB", "CCC"};
    private static HashMap<Character, String> myMap;

    private MyClass() {
        System.out.println("Running constructor");
        populateMyMap();
    }

    private static void populateMyMap() {
        myMap = new HashMap<Character, String>();
        for (int i=0; i < KEYS.length; i++) {
            myMap.put(KEYS.charAt(i), DATA[i]);
        }
    }

    //various static methods
}

Правильно ли использовать здесь частный конструктор, и если да, то что я делаю не так?

Извините, если это дубликат; Я пытался искать ответы, но я не уверен, что искать!

Ответы [ 4 ]

8 голосов
/ 12 января 2012

Нет, приватный конструктор - это не то, что вам нужно.Конструктор инициализирует экземпляр вашего класса (когда вы вызываете new MyClass()), но статическое состояние не принадлежит экземпляру и поэтому не должно инициализироваться из конструктора.Инициализация, которую вы хотите выполнить при первой загрузке класса, должна быть в блоке static, размещенном на уровне класса.

static {
   populateMyMap();
}

Но вы никогда не должны использовать статическое (глобальное) состояние.Статическое состояние делает вашу систему непросто трудной для тестирования, оно более детализировано, чем состояние экземпляра (например, у вас есть одна копия на загрузку класса), и, как правило, труднее сделать потокобезопасным.вместо этого сопоставьте член экземпляра вашего класса.

5 голосов
/ 12 января 2012

Статический блок инициализатора был упомянут в нескольких других ответах.Но практически в дикой природе я нахожу следующую идиому:

public class MyClass
{
    private static HashMap<Character, String> myMap = createMyMap();

    private static HashMap<Character, String> createMyMap() {
        HashMap<Character, String> myTmpMap = new HashMap<Character, String>();
        for (int i=0; i < KEYS.length; i++) {
            myTmpMap.put(KEYS.charAt(i), DATA[i]);
        }
        return myTmpMap;
    }
}
3 голосов
/ 12 января 2012

Используйте статический инициализатор:

public class MyClass
{
    static {
    //init
    }
}
0 голосов
/ 12 января 2012

Есть два способа достичь этого. Один из них заключается в том, чтобы сделать метод «populateMyMap» статическим инициализатором (или подход, предложенный A.H.). Тогда он гарантированно будет выполнен перед первым статическим вызовом. Обычно это лучший способ, если предположить, что либо стоимость запуска populateMyMap достаточно мала, чтобы не быть замеченной, либо если вы собираетесь использовать функциональные возможности класса почти каждый раз, когда запускается приложение.

Альтернативный подход - это то, что вы использовали бы, если бы выполнение «populateMyMap» занимало значительное количество времени И либо вы либо не используете функциональность для некоторых выполнений приложения, либо хотите отложить выполнение populateMyMap до тех пор, пока данные не понадобятся, чтобы не излишне увеличивать время запуска.

Если вам нужен второй подход, вам следует переключать структуры и использовать Singleton, а не статические методы. Сделайте методы (и данные) нестатичными, и каждый из них получит экземпляр Singleton перед вызовом метода. Вызовите «populateMyMap» в (приватном) конструкторе. Да, я знаю, у синглетонов плохая репутация, и люди всегда говорят: «Избегайте их, потому что они просто замаскированные глобальные методы», но статические методы также являются просто глобальными методами. Вы ничего не теряете. И таким образом вы не оплачиваете стоимость выполнения populateMyMap до тех пор, пока вам не понадобится (или за исключением случаев).

ВНИМАНИЕ: Если ваши структуры данных не являются неизменяемыми, то есть они могут быть изменены после их инициализации, то вам, вероятно, не следует использовать любую из этих структур.

...