Инициализация конечных полей в 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 не инициализируется.