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

В Java может быть инициализировано окончательное поле из помощника конструктора?

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

private final HashMap<String,String> myMap;

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

Я мог бы реализовать код инициализации 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...
}
4b9b3361

Ответ 1

Метод №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...
  }

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

Ответ 2

Как насчет реализации частного конструктора, который инициализирует ваш 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.
}

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

Ответ 3

Вариант № 2 является наиболее подходящим вариантом, потому что вы можете поделиться им со всеми конструкторами. Здесь нам понадобятся инициализаторы коллекции С#.:)

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