Инициализация конечных полей в Java
У меня есть класс с множеством конечных элементов, которые могут быть созданы с использованием одного из двух конструкторов. Конструкторы имеют некоторый код, который хранится в третьем конструкторе.
// SubTypeOne and SubTypeTwo both extend SuperType
public class MyClass {
private final SomeType one;
private final SuperType two;
private MyClass(SomeType commonArg) {
one = commonArg;
}
public MyClass(SomeType commonArg, int intIn) {
this(commonArg);
two = new SubTypeOne(intIn);
}
public MyClass(SomeType commonArg, String stringIn) {
this(commonArg);
two = new SubTypeTwo(stringIn);
}
Проблема заключается в том, что этот код не компилируется: Variable 'two' might not have been initialized.
Кто-то может вызвать первый конструктор из MyClass, а затем новый объект не будет иметь "два" поля.
Итак, каков предпочтительный способ совместного использования кода между конструкторами в этом случае? Обычно я использую вспомогательный метод, но общий код должен иметь возможность устанавливать конечные переменные, которые могут выполняться только из конструктора.
Ответы
Ответ 1
Как насчет этого? (Обновлено для измененного вопроса)
public class MyClass {
private final SomeType one;
private final SuperType two;
public MyClass (SomeType commonArg, int intIn) {
this(commonArg, new SubTypeOne(intIn));
}
public MyClass (SomeType commonArg, String stringIn) {
this(commonArg, new SubTypeTwo(stringIn));
}
private MyClass (SomeType commonArg, SuperType twoIn) {
one = commonArg;
two = twoIn;
}
}
Ответ 2
Вам нужно убедиться, что в каждом конструкторе вы инициализируете все конечные переменные. Я бы сделал один конструктор, который инициализирует все переменные и имеет все остальные вызовы конструктора, передавая в null
или какое-то значение по умолчанию, если есть поле, для которого им не присвоено значение.
Пример:
public class MyClass {
private final SomeType one;
private final SuperType two;
//constructor that initializes all variables
public MyClas(SomeType _one, SuperType _two) {
one = _one;
two = _two;
}
private MyClass(SomeType _one) {
this(_one, null);
}
public MyClass(SomeType _one, SubTypeOne _two) {
this(_one, _two);
}
public MyClass(SomeType _one, SubTypeTwo _two) {
this(_one, _two);
}
}
Ответ 3
Все, что вам нужно сделать, это убедиться, что "два" инициализируются. В первом конструкторе просто добавьте:
two = null;
если нет другого значения, которое вы хотели бы дать в случае, когда вызывается только первый конструктор.
Ответ 4
Вы получите эту ошибку, потому что, если вы вызвали MyClass(SomeType oneIn)
, two
не инициализируется.