Есть, конечно, технические отличия (вы могли бы вызвать статический метод несколько раз в своем классе, если хотите, вы могли бы вызывать его через отражение и т. Д.), Но, предполагая, что вы не делаете ничего из этого обмана, Правильно - оба подхода фактически идентичны.
Я также предпочитаю подход, основанный на методе, поскольку он дает красивое имя блоку кода. Но это почти полностью стилистический подход.
Как указывает Марко, метод, основанный на методе, также служит для разделения двух проблем создания Person и назначения его статической переменной. Со статическим блоком эти две вещи объединены, что может ухудшить читаемость, если блок не является тривиальным. Но с помощью метода метод отвечает исключительно для создания объекта, а инициализация статической переменной отвечает исключительно для получения результата этого метода и назначения его переменной.
Принимая это немного дальше: если у меня есть два статических поля, а один зависит от другого, то я объявлю два метода и второй метод беру первую переменную в качестве явного аргумента. Мне нравится сохранять мои статические методы инициализации полностью без состояния, что значительно облегчает рассуждение о том, что должно произойти, когда (и какие переменные, которые он предполагает, уже созданы).
Так, что-то вроде:
public class Test {
public static final Person p = initPerson();
public static final String pAddress = lookupAddress(p);
/* implementations of initPerson and lookupAddress omitted */
}
Это очень ясно, смотря на то, что (а) вам не нужно pAddress
инициализировать p
, и (б) вы сделать необходимо p
для инициализации lookupAddress
.На самом деле, компилятор даст вам ошибку компиляции («незаконная опережающую ссылку»), если вы пробовали их в обратном порядке, и ваши статические поля были не- final
:
public static String pAddress = lookupAddress(p); // ERROR
public static Person p = initPerson();
Вы бы потерять эту ясность и безопасность с статическим блоки. Это компилируется нормально:
static {
pAddress = p.findAddressSomehow();
p = new Person();
}
... но это будет не в состоянии во время выполнения, так как в p.findAddressSomehow()
, p
имеет значение null
по умолчанию.
, поэтому для подведения итогов как статический блок, так и статическая часть инициализации будет выполняться только один раз - это то, что вы имеете в виду правильно. – vikeng21
Это правильно. – yshavit
Это не просто название блока, также важно обращение к управлению: метод просто * возвращает * значение, тогда как блок init вставляет его в переменную. Поскольку система статического типа гарантирует, что метод вернет значение, это способствует удобочитаемости и правильности. Блок init может выполнять или не выполнять назначение, и между блоком инициализации и переменной нет жесткой связи. –