Статический блок инициализации — это блок кода, выполняемый при первоначальной загрузке класса JVM до первого использования любого статического члена или создания экземпляра класса.
История вопроса:
Java с самого начала предоставляла статические поля для хранения общих для всех экземпляров значений. Для нестандартной инициализации или комплексных вычислений при старте класса ввели static-блоки.
Проблема:
Обычные статические поля можно инициализировать непосредственно при объявлении, но когда инициализация долгая, требует обращения к другим классам/файлам/БД, или зависит от сложной логики, приходится использовать static-блоки. Неправильное использование static-блоков может привести к неожиданному поведению при загрузке классов, трудностям при тестировании и даже к deadlock'ам.
Решение:
Static-блоки используют только для сложной инициализации статических ресурсов, когда их невозможно выразить через одно выражение. Хороший пример — загрузка JDBC-драйверов, считывание конфигов:
public class Config { public static Properties properties; static { properties = new Properties(); try (InputStream in = new FileInputStream("config.properties")) { properties.load(in); } catch (IOException e) { throw new ExceptionInInitializerError(e); } } }
Ключевые особенности:
Можно ли использовать return внутри статического блока?
Нет, оператор return недопустим в static-блоках. Можно использовать throw для выброса исключения.
Когда выполняется статический блок — при загрузке класса или при создании объекта?
Статический блок выполняется один раз при загрузке класса, даже если ни одного объекта так и не будет создано.
Могут ли быть несколько static-блоков в одном классе? В каком порядке они выполняются?
Да, можно объявить несколько статических блоков. Они выполняются в порядке появления в коде классов.
В классе static-блок читает большой файл и соединяется с внешним сервисом. В тестах или простых утилитах класс JVM грузится медленно.
Плюсы:
Минусы:
Static-блок проверяет наличие лицензии ПО при старте, выбрасывает ExceptionInInitializerError при ошибке.
Плюсы:
Минусы: