В общем, не используйте нестатические блоки инициализатора (и, возможно, избегайте статических).
Запутанный синтаксис
Глядя на этот вопрос, есть 3 ответа, но вы обманули 4 человек с этим синтаксисом. Я был одним из них, и я пишу на Java в течение 16 лет! Очевидно, что синтаксис потенциально подвержен ошибкам! Я бы держался подальше от этого.
Телескопические Конструкторы
Для действительно простых вещей вы можете использовать «телескопические» конструкторы, чтобы избежать этой путаницы:
public class Test {
private String something;
// Default constructor does some things
public Test() { doStuff(); }
// Other constructors call the default constructor
public Test(String s) {
this(); // Call default constructor
something = s;
}
}
Образец Строителя
Если вам нужно сделать doStuff () в конце каждого конструктора или другой сложной инициализации, возможно, будет лучше использовать шаблон компоновщика. Джош Блох перечисляет несколько причин, почему строители - хорошая идея. Строителям требуется немного времени для написания, но правильно написано, что ими приятно пользоваться.
public class Test {
// Value can be final (immutable)
private final String something;
// Private constructor.
private Test(String s) { something = s; }
// Static method to get a builder
public static Builder builder() { return new Builder(); }
// builder class accumulates values until a valid Test object can be created.
private static class Builder {
private String tempSomething;
public Builder something(String s) {
tempSomething = s;
return this;
}
// This is our factory method for a Test class.
public Test build() {
Test t = new Test(tempSomething);
// Here we do your extra initialization after the
// Test class has been created.
doStuff();
// Return a valid, potentially immutable Test object.
return t;
}
}
}
// Now you can call:
Test t = Test.builder()
.setString("Utini!")
.build();
Петли статического инициализатора
Я использовал статический инициализаторы, но иногда сталкивался с циклами, в которых 2 класса зависели от того, как блоки статического инициализатора друг друга вызывались до того, как класс мог быть полностью загружен. Это приводило к «не удалось загрузить класс» или аналогично расплывчатое сообщение об ошибке. Мне пришлось сравнить файлы с последней известной рабочей версией в системе контроля версий, чтобы выяснить, в чем проблема. Не весело вообще.
Ленивая инициализация
Возможно, статические инициализаторы хороши по причинам производительности, когда они работают, и не слишком запутаны. Но в целом я предпочитаю ленивую инициализацию статическим инициализаторам в эти дни. Понятно, что они делают, я еще не сталкивался с ними при загрузке классов, и они работают в большем количестве ситуаций инициализации, чем блоки инициализатора.
Определение данных
Вместо статической инициализации для построения структур данных (сравните с примерами в других ответах), теперь я использую вспомогательные функции определения неизменных данных Paguro :
private ImMap<String,String> days =
map(tup("mon", "monday"),
tup("tue", "tuesday"),
tup("wed", "wednesday"),
tup("thu", "thursday"),
tup("fri", "friday"),
tup("sat", "saturday"),
tup("sun", "sunday"));
Conculsion
В начале Java блоки инициализатора были единственным способом сделать что-то, но теперь они сбивают с толку, подвержены ошибкам и в большинстве случаев были заменены лучшими альтернативами (подробно описано выше). Интересно узнать о блоках инициализатора, если вы видите их в унаследованном коде или они проходят тестирование, но если бы я делал обзор кода и видел один в новом коде, я бы попросил вас объяснить, почему ни один из вышеупомянутые альтернативы были подходящими, прежде чем дать ваш код большой палец вверх.