← Назад к вопросам

Приведи пример static блока

2.0 Middle🔥 191 комментариев
#Docker, Kubernetes и DevOps#JVM и управление памятью#ORM и Hibernate

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Приведи пример static блока

Рассмотрим static блоки в Java — это конструкции, которые выполняются один раз при загрузке класса.

Что такое static блок?

Static блок — это блок инициализации, который:

  • Выполняется только один раз при загрузке класса
  • Выполняется ДО создания первого объекта
  • Используется для инициализации static переменных
  • Не имеет доступа к instance переменным (только к static)

Базовый пример

public class ConfigLoader {
    private static int maxConnections;
    private static String appName;
    
    // Static блок выполняется при загрузке класса
    static {
        System.out.println("ConfigLoader loaded!");
        maxConnections = 100;
        appName = "MyApp";
    }
    
    public static void main(String[] args) {
        System.out.println("Max connections: " + maxConnections);
        System.out.println("App name: " + appName);
    }
}

// Вывод:
// ConfigLoader loaded!   (static блок)
// Max connections: 100
// App name: MyApp

Замечаете, что строка "ConfigLoader loaded!" напечаталась ДО содержимого main? Это потому что static блок выполнится раньше.

Реальный пример: инициализация логирования

import java.util.logging.Logger;
import java.util.logging.Level;

public class Application {
    private static final Logger LOGGER = Logger.getLogger(Application.class.getName());
    private static boolean isProduction;
    private static String databaseUrl;
    
    static {
        // Читаем переменные окружения при загрузке класса
        String env = System.getenv("APP_ENV");
        isProduction = "production".equalsIgnoreCase(env);
        
        databaseUrl = isProduction 
            ? "jdbc:postgresql://prod-db.example.com:5432/app"
            : "jdbc:h2:mem:testdb";
        
        // Настраиваем логирование
        if (isProduction) {
            LOGGER.setLevel(Level.WARNING);
        } else {
            LOGGER.setLevel(Level.FINE);
        }
        
        LOGGER.info("Application initialized in " + env + " mode");
        LOGGER.info("Database: " + databaseUrl);
    }
    
    public static void main(String[] args) {
        LOGGER.info("Application started");
    }
}

// При запуске в production:
// DATABASE: jdbc:postgresql://prod-db.example.com:5432/app
// Application initialized in production mode
// Application started

Пример 2: инициализация connection pool

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class Database {
    private static HikariDataSource dataSource;
    private static final int POOL_SIZE = 10;
    private static final String DB_URL = "jdbc:postgresql://localhost/mydb";
    
    static {
        System.out.println("Initializing database connection pool...");
        
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(DB_URL);
        config.setUsername("postgres");
        config.setPassword("password");
        config.setMaximumPoolSize(POOL_SIZE);
        config.setMinimumIdle(2);
        config.setConnectionTimeout(10000);
        
        dataSource = new HikariDataSource(config);
        
        System.out.println("Database pool ready with " + POOL_SIZE + " connections");
    }
    
    public static HikariDataSource getDataSource() {
        return dataSource;
    }
}

// Вывод при загрузке:
// Initializing database connection pool...
// Database pool ready with 10 connections

Пример 3: инициализация коллекций

import java.util.*;

public class StatusCodes {
    private static final Map<Integer, String> STATUS_MAP;
    private static final Set<String> ALLOWED_ROLES;
    
    // Static блок инициализирует Collections
    static {
        // Инициализация MAP
        STATUS_MAP = new HashMap<>();
        STATUS_MAP.put(200, "OK");
        STATUS_MAP.put(201, "Created");
        STATUS_MAP.put(400, "Bad Request");
        STATUS_MAP.put(401, "Unauthorized");
        STATUS_MAP.put(404, "Not Found");
        STATUS_MAP.put(500, "Internal Server Error");
        
        // Инициализация SET
        ALLOWED_ROLES = new HashSet<>();
        ALLOWED_ROLES.add("ADMIN");
        ALLOWED_ROLES.add("USER");
        ALLOWED_ROLES.add("MODERATOR");
    }
    
    public static String getStatusMessage(int code) {
        return STATUS_MAP.getOrDefault(code, "Unknown");
    }
    
    public static boolean isValidRole(String role) {
        return ALLOWED_ROLES.contains(role);
    }
    
    public static void main(String[] args) {
        System.out.println(getStatusMessage(404));    // Not Found
        System.out.println(isValidRole("ADMIN"));     // true
        System.out.println(isValidRole("SUPERUSER")); // false
    }
}

Пример 4: множественные static блоки

В классе может быть несколько static блоков, они выполняются по порядку:

public class InitializationOrder {
    private static int counter = 0;
    
    static {
        counter = 1;
        System.out.println("Static block 1, counter = " + counter);
    }
    
    static {
        counter = 2;
        System.out.println("Static block 2, counter = " + counter);
    }
    
    static {
        counter = 3;
        System.out.println("Static block 3, counter = " + counter);
    }
    
    public static void main(String[] args) {
        System.out.println("Main method, counter = " + counter);
    }
}

// Вывод:
// Static block 1, counter = 1
// Static block 2, counter = 2
// Static block 3, counter = 3
// Main method, counter = 3

Static блок vs Конструктор

public class Comparison {
    private static int staticCounter = 0;   // Static переменная
    private int instanceCounter = 0;        // Instance переменная
    
    // STATIC блок - выполняется один раз при загрузке класса
    static {
        staticCounter = 100;
        System.out.println("Static block executed once");
    }
    
    // Конструктор - выполняется каждый раз при создании объекта
    public Comparison() {
        instanceCounter = 10;
        System.out.println("Constructor executed");
    }
    
    public static void main(String[] args) {
        System.out.println("Before creating objects\n");
        
        Comparison obj1 = new Comparison();  // Конструктор вызовется
        System.out.println();
        
        Comparison obj2 = new Comparison();  // Конструктор вызовется ещё раз
        System.out.println();
        
        System.out.println("Static counter: " + Comparison.staticCounter);
    }
}

// Вывод:
// Static block executed once          (один раз)
// Before creating objects
// Constructor executed                (первый объект)
// Constructor executed                (второй объект)
// Static counter: 100

Практическое применение

1. Инициализация сложных ресурсов

public class EmailService {
    private static JavaMailSender mailSender;
    
    static {
        SimpleMailMessage message = new SimpleMailMessage();
        // Настройка почты один раз
        mailSender = createMailSender();
    }
    
    private static JavaMailSender createMailSender() {
        // Тяжёлая операция инициализации
        return null;
    }
}

2. Загрузка конфигурации

public class AppConfig {
    public static final Properties CONFIG;
    
    static {
        CONFIG = new Properties();
        try {
            CONFIG.load(AppConfig.class.getResourceAsStream("/app.properties"));
        } catch (IOException e) {
            throw new ExceptionInInitializerError("Cannot load config", e);
        }
    }
}

Ключевые моменты

  • Выполняется один раз при загрузке класса
  • Выполняется ДО первого обращения к классу
  • Выполняется ДО создания первого объекта
  • Можно несколько static блоков — выполняются по порядку
  • Используется для инициализации static переменных и ресурсов
  • Нет доступа к instance переменным
  • Исключения в static блоке приводят к ExceptionInInitializerError
Приведи пример static блока | PrepBro