Взагалі, не використовуйте нестатичні блоки ініціалізатора (і, можливо, також уникайте статичних).
Заплутаний синтаксис
Дивлячись на це запитання, є 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 класи залежали від виклику статичних блоків статичних ініціалізаторів один одного до того, як клас міг бути повністю завантажений. Це призвело до невдалого завантаження класу або подібного розпливчастого повідомлення про помилку. Мені довелося порівняти файли з останньою відомою робочою версією в керуванні джерелами, щоб зрозуміти, в чому проблема. Не весело взагалі.
Ледача ініціалізація
Можливо, статичні ініціалізатори хороші з міркувань продуктивності, коли вони працюють і не надто заплутані. Але загалом я віддаю перевагу лінивій ініціалізації перед статичними ініціалізаторами в наші дні. Зрозуміло, що вони роблять, я ще не натрапив на помилку завантаження класу з ними, і вони працюють у більшій кількості ситуацій ініціалізації, ніж у блоках ініціалізаторів.
Визначення даних
Замість статичної ініціалізації для побудови структур даних (порівняйте з прикладами в інших відповідях) я тепер використовую допоміжні функції визначення даних Пагуро :
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"));
Висновок
На початку Java блоки ініціалізатора були єдиним способом зробити деякі речі, але тепер вони заплутані, схильні до помилок і в більшості випадків були замінені кращими альтернативами (детальніше вище). Цікаво знати про ініціалізаційні блоки на випадок, якщо ви бачите їх у застарілому коді, або вони виходять на тест, але якщо я робив огляд коду і бачив його в новому коді, прошу вас обґрунтувати, чому жоден із вище альтернативи були придатні, перш ніж надавати свій код великими пальцями.