В Java может ли конечное поле быть инициализировано из помощника конструктора? - PullRequest
40 голосов
/ 18 мая 2010

У меня есть последний нестатический член:

private final HashMap<String,String> myMap;

Я хотел бы инициализировать его с помощью метода, вызываемого конструктором.Поскольку myMap является окончательным, мой «вспомогательный» метод не может инициализировать его напрямую.Конечно, у меня есть варианты:

Я мог бы реализовать код инициализации myMap непосредственно в конструкторе.

MyConstructor (String someThingNecessary)
{
    myMap = new HashMap<String,String>();

    myMap.put("blah","blahblah");
    // etc...

    // other initialization stuff unrelated to myMap
}

Я мог бы заставить мой вспомогательный метод собрать HashMap, вернуть его конструктору ипусть конструктор затем назначит объект myMap.

MyConstructor (String someThingNecessary)
{
    myMap = InitializeMyMap(someThingNecessary);

    // other initialization stuff unrelated to myMap
}

private HashMap<String,String> InitializeMyMap(String someThingNecessary)
{
    HashMap<String,String> initializedMap = new HashMap<String,String>();

    initializedMap.put("blah","blahblah");
    // etc...

    return initializedMap;
}

Метод # 2 подойдет, однако мне интересно, есть ли способ, которым я мог бы позволить вспомогательному методу напрямую манипулировать myMap.Возможно, модификатор, который указывает, что он может быть вызван только конструктором?

MyConstructor (String someThingNecessary)
{
    InitializeMyMap(someThingNecessary);

    // other initialization stuff unrelated to myMap
}


// helper doesn't work since it can't modify a final member
private void InitializeMyMap(String someThingNecessary)
{
    myMap = new HashMap<String,String>();

    myMap.put("blah","blahblah");
    // etc...
}

Ответы [ 3 ]

13 голосов
/ 05 июля 2011

Как насчет реализации частного конструктора, который инициализирует ваш HashMap, а затем ваш основной конструктор (ы) вызывает этот закрытый конструктор?

Например -

// Helper function to initialize final HashMap.
private MyConstructor()
{
    myMap = new HashMap<String,String>();
    myMap.put("blah","blah");
}

MyConstructor (String someThingNecessary)
{
    // Initialize the HashMap.
    this();
    // Other initialization code can follow.
}

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

13 голосов
/ 18 мая 2010

Метод №2 - ваш лучший вариант. Проблема в том, что если у вас есть присваивание в приватном методе, ничто не мешает другому коду в классе вне вызывающего его конструктора, что может создать проблему с попыткой второго присваивания конечному полю.

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

Для полноты мы можем сделать третий вариант, когда вы назначаете карту при инициализации и затем заполняете ее вспомогательным методом:

 private final HashMap<String, String> myMap = new HashMap<String, String();

А потом:

 MyConstructor (String someThingNecessary)
 {
    initializeMyMap(someThingNecessary);

    // other initialization stuff unrelated to myMap
 }


 // helper doesn't work since it can't modify a final member
 private void initializeMyMap(String someThingNecessary)
 {

     myMap.clear();
    myMap.put("blah","blahblah");
    // etc...
  }

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

1 голос
/ 18 мая 2010

Опция # 2 является наиболее пригодной для повторения, потому что вы можете поделиться ею со всеми конструкторами. Здесь нам понадобятся инициализаторы коллекции c #. :)

(Кстати: # 3 не будет компилироваться)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...