Java Academy · Урок

Статические поля и константы

Используйте статические поля для общего состояния, константы с static final и статические инициализаторы.

Урок 3 из 413 шагов

«Статические поля и константы» — бесплатный урок Java Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Статические поля и константы

Статические поля принадлежат классу, а не экземплярам. Они совместно используются всеми объектами этого класса. Константы объединяют модификаторы static и final, создавая неизменяемые значения на уровне класса.

Статические поля и поля экземпляра

У каждого объекта есть отдельная копия поля экземпляра. Статическое поле существует в единственном экземпляре и совместно используется всеми объектами класса.

class Counter {
    private static int totalCount = 0;  // shared across all instances
    private int instanceId;              // unique per instance

    Counter() {
        totalCount++;
        instanceId = totalCount;
    }

    static int getTotalCount() { return totalCount; }
    int getInstanceId()        { return instanceId; }
}

Counter c1 = new Counter();
Counter c2 = new Counter();
Counter c3 = new Counter();

System.out.println(Counter.getTotalCount()); // 3
System.out.println(c1.getInstanceId());       // 1
System.out.println(c3.getInstanceId());       // 3

Константы с static final

Объявляйте константы как public static final. По соглашению для их имён используют SCREAMING_SNAKE_CASE.

class MathConstants {
    public static final double PI      = 3.141592653589793;
    public static final double E       = 2.718281828459045;
    public static final double GOLDEN  = 1.618033988749895;
    public static final int    PRIMES[] = {2, 3, 5, 7, 11, 13};
}

// Access without an instance
System.out.println(MathConstants.PI);

// Constants on domain classes
class HttpStatus {
    public static final int OK        = 200;
    public static final int NOT_FOUND = 404;
    public static final int SERVER_ERR = 500;
}

Блоки статической инициализации

Если константа требует сложной инициализации, используйте блок статической инициализации, который выполняется один раз при загрузке класса.

import java.util.*;

class Config {
    public static final Map<String, String> DEFAULTS;

    static {
        Map<String, String> map = new HashMap<>();
        map.put("timeout",  "30");
        map.put("maxRetry", "3");
        map.put("logLevel", "INFO");
        DEFAULTS = Collections.unmodifiableMap(map);
    }
}

System.out.println(Config.DEFAULTS.get("timeout")); // 30

Шаблон статического счётчика

Статические поля часто используют для генерации ID, подсчёта метрик или хранения общих кэшей.

import java.util.concurrent.atomic.AtomicLong;

class Order {
    private static final AtomicLong ID_SEQUENCE = new AtomicLong(1000);

    private final long id;
    private final String item;

    Order(String item) {
        this.id   = ID_SEQUENCE.getAndIncrement();
        this.item = item;
    }

    long getId()   { return id; }
    String getItem() { return item; }
}

Order o1 = new Order("Laptop");
Order o2 = new Order("Mouse");
System.out.println(o1.getId()); // 1000
System.out.println(o2.getId()); // 1001

Одиночка через статическое поле

В шаблоне одиночки статическое поле хранит единственный экземпляр. Используйте ленивую инициализацию для классов, которые могут потребоваться не всегда.

class DatabasePool {
    private static volatile DatabasePool instance;
    private final int maxConnections;

    private DatabasePool() { this.maxConnections = 20; }

    public static DatabasePool getInstance() {
        if (instance == null) {
            synchronized (DatabasePool.class) {
                if (instance == null)
                    instance = new DatabasePool();
            }
        }
        return instance;
    }

    public int getMaxConnections() { return maxConnections; }
}

System.out.println(DatabasePool.getInstance().getMaxConnections()); // 20

Статический импорт

import static позволяет использовать статические члены без префикса с именем класса — это удобно для констант и вспомогательных методов.

import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
import static java.lang.Math.pow;

// Without import static: Math.PI * Math.pow(r, 2)
double radius = 5.0;
double area = PI * pow(radius, 2);
System.out.printf("Area: %.2f%n", area); // 78.54

// Caution: overuse of static imports hurts readability
// Acceptable for: Math.*, Assert.* in tests, TimeUnit

Потокобезопасность статических полей

Статические поля, совместно используемые несколькими потоками, требуют синхронизации или атомарных типов, чтобы избежать состояний гонки.

import java.util.concurrent.atomic.*;

class RequestMetrics {
    private static final AtomicLong requestCount  = new AtomicLong(0);
    private static final AtomicLong totalLatencyMs = new AtomicLong(0);

    public static void record(long latencyMs) {
        requestCount.incrementAndGet();
        totalLatencyMs.addAndGet(latencyMs);
    }

    public static double averageLatency() {
        long count = requestCount.get();
        return count == 0 ? 0 : (double) totalLatencyMs.get() / count;
    }
}
RequestMetrics.record(45);
RequestMetrics.record(120);
System.out.println(RequestMetrics.averageLatency()); // 82.5

Изменяемые статические поля: подводные камни

Изменяемые статические поля опасны: глобальное изменяемое состояние сложно тестировать, без особой осторожности оно небезопасно в многопоточном коде и создаёт скрытую связанность между классами.

// BAD: mutable static state
class GlobalConfig {
    public static String environment = "dev"; // mutable global!
}
// Any code anywhere can change GlobalConfig.environment
// Very hard to test, unexpected interactions

// BETTER: immutable constant
class GlobalConfig2 {
    public static final String ENVIRONMENT =
        System.getenv().getOrDefault("APP_ENV", "dev");
}

// BEST: inject via constructor (dependency injection)
class Service {
    private final String environment;
    Service(String environment) { this.environment = environment; }
}

Антипаттерн интерфейса констант

Использовать интерфейс для хранения констант (антипаттерн «интерфейс констант») не рекомендуется. Вместо этого используйте класс с приватным конструктором.

// BAD: constant interface — pollutes the namespace of implementing classes
interface FinancialConstants {
    double TAX_RATE = 0.08;  // implicitly public static final
}

// GOOD: utility class for constants
final class FinancialConstants2 {
    private FinancialConstants2() {} // prevent instantiation

    public static final double TAX_RATE  = 0.08;
    public static final double VAT_RATE  = 0.20;
    public static final int    MAX_ITEMS = 100;
}
System.out.println(FinancialConstants2.TAX_RATE); // 0.08

Практика: флаги функций через константы

Использование констант static final типа boolean в качестве флагов функций, обрабатываемых во время компиляции: JIT-компилятор удаляет недостижимые ветви.

class Features {
    public static final boolean ENABLE_ANALYTICS   = true;
    public static final boolean ENABLE_AI_SEARCH    = false;
    public static final boolean DEBUG_MODE          =
        "true".equals(System.getenv("DEBUG"));
}

// The JIT eliminates this if-block when ENABLE_AI_SEARCH is false:
if (Features.ENABLE_AI_SEARCH) {
    System.out.println("Running AI search...");
}

if (Features.DEBUG_MODE) {
    System.out.println("[DEBUG] Request received");
}

Быстрая проверка

В чём разница между статическим полем и полем экземпляра?

Итоги: статические поля и константы

Ключевые выводы:

  • Статические поля принадлежат классу — существует одна копия, совместно используемая всеми экземплярами
  • Константы: public static final UPPER_SNAKE_CASE
  • Используйте блоки статической инициализации для констант, требующих сложной инициализации
  • В многопоточном коде для изменяемых статических полей отдавайте предпочтение AtomicLong/AtomicInteger
  • Избегайте изменяемых статических полей — они создают скрытое глобальное состояние, которое сложно тестировать
  • Для констант используйте класс, который нельзя создать (с приватным конструктором), а не интерфейс
Можно начать бесплатно

Изучай Java с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
104
Уроки
374

Часто задаваемые вопросы

Урок «Статические поля и константы» бесплатный?

Да — полный текст урока «Статические поля и константы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Статические поля и константы»?

Используйте статические поля для общего состояния, константы с static final и статические инициализаторы. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Статические поля и константы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Правила перегрузки методов
  2. Параметры переменной длины
  3. Статические поля и константы
  4. Вспомогательные классы и статические фабричные методы
← Назад к Java Academy