Инициализация конечных свойств с использованием вспомогательных приватных методов - PullRequest
2 голосов
/ 06 декабря 2011

У меня есть несколько финальных свойств, определенных в классе Java с конструктором, который имеет всю информацию для инициализации свойств.

public final class A {
   private final Object prop1;
   private final Object prop2;

   public A(Object someObj, String prop1Str, String prop2Str) {
       //initialize prop1 and prop2 based on information provided from someObj, prop1Str and prop2Str parameter (1)
   }
}

Я хотел бы представить новый конструктор в классе A со следующей сигнатурой и семантикой

   public A(Object obj1, Object obj2, String prop1Str, String prop2Str) {
       //use obj1 and obj2 to initialize the someObj
       //initialize prop1 and prop2 based on information provided from someObj, prop1Str and prop2Str parameter (1)
   }

Как я могу повторно использовать код в (1)? Я пытался использовать вспомогательные закрытые методы, но Java6 выдает ошибку компиляции, поскольку свойства класса являются окончательными и, возможно, они не были инициализированы.

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

Ответы [ 3 ]

3 голосов
/ 06 декабря 2011

Вы нашли недостаток final: -)

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

Обходные:

  1. Используйте static вспомогательные методы (которые по своей структуре не зависят от состояния класса и, следовательно, от любых полей final).

  2. Используйте шаблон построителя (поместите все параметры в вспомогательный класс, у которого есть метод build(), который возвращает желаемый результат).

  3. Не использовать final. Вы можете получить то же событие, опуская сеттеры. Если вы боитесь, что код в классе может изменить поля, переместите их в новый базовый класс.

0 голосов
/ 06 декабря 2011

Во-первых, вы уверены, что ваши конструкторы не выходят из-под контроля?

Если вы намерены (на данный момент) перейти ко многим корням конструктора, то вы можете вызывать одного конструктора из другого. Должна быть первой строкой конструктора, использующего синтаксис this();, который заменяет неявный или явный super();.

public A(Object obj, String prop1Str, String prop2Str) {
    this(obj, obj, prop1Str, prop2Str);
}
public A(Object obj1, Object obj2, String prop1Str, String prop2Str) {
    // ...
}

Конечно, вы можете преобразовывать аргументы, используя более сложные выражения вместо простого переданного аргумента. Например:

public A(Object obj, Object prop1Obj, String prop2Str) {
    this(obj, maskNull(obj), String.valueOf(prop1Str), prop2Str);
}

Конструкторы предназначены для инициализации объекта в допустимое состояние. Для более сложной обработки вы можете добавить статический метод создания. Этот метод может даже иметь имя, означающее, что он указывает на то, что он делает.

0 голосов
/ 06 декабря 2011

Вам следует позвонить this(obj1, prop1Str, prop2Str).Это должна быть первая исполняемая строка во втором конструкторе.

...