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

К чему относятся статические переменные

2.0 Middle🔥 151 комментариев
#Основы Java

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

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

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

# Статические переменные в Java

Определение

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

Ключевое различие

Обычные (нестатические) переменные

public class Car {
    private String color;  // каждый объект имеет свой цвет
}

Car car1 = new Car();
Car car2 = new Car();

car1.color = "red";   // красная машина
car2.color = "blue";  // синяя машина

// Каждый объект имеет ОТдельный color

Статические переменные

public class Car {
    static int totalCars = 0;  // общее для ВСЕх машин
    private String color;
}

Car car1 = new Car();
car1.totalCars++;  // 1

Car car2 = new Car();
car2.totalCars++;  // 2

System.out.println(Car.totalCars);  // 2 (ОДИН счётчик для всех)

К чему относятся статические переменные

Вариант 1: К КЛАССУ (основной ответ)

Статические переменные принадлежат КЛАССУ, не экземплярам.

Это означает:

  • Одна переменная на весь класс (не на каждый объект)
  • Живёт в памяти с загрузкой класса
  • Доступна через имя класса: ClassName.staticVar
  • Общая для всех объектов класса
public class Database {
    static String connection = "localhost:5432";  // одна на все
    
    String userName;  // каждый объект свой
}

// Обращение
Database.connection;  // Через класс
Database db = new Database();
db.connection;  // Можно, но неправильно (выглядит как экземпляр)

Вариант 2: К ПАМЯТИ (техническая сторона)

Визуально:

МОДЕЛЬ ПАМЯТИ JAVA:

┌─────────────────────────────────────┐
│      HEAP (Куча)                    │
│                                     │
│  Car object #1                      │ ← каждый объект имеет свой
│  ├─ color: "red"                    │   экземпляр нестатических
│  └─ id: 1                           │   переменных
│                                     │
│  Car object #2                      │
│  ├─ color: "blue"                   │
│  └─ id: 2                           │
└─────────────────────────────────────┘

┌─────────────────────────────────────┐
│  STATIC MEMORY (Статическая память) │
│                                     │
│  Car.totalCars = 2  ← ОДНА НА ВСЕх  │
│  Car.maxSpeed = 300                 │
│  Database.connection = ...          │
└─────────────────────────────────────┘

Примеры использования

Пример 1: Счётчик объектов

public class Student {
    static int studentCount = 0;  // статическая переменная
    private String name;
    
    public Student(String name) {
        this.name = name;
        studentCount++;  // увеличиваем счётчик
    }
}

// Использование
Student s1 = new Student("Ivan");
System.out.println(Student.studentCount);  // 1

Student s2 = new Student("Maria");
System.out.println(Student.studentCount);  // 2

Student s3 = new Student("Peter");
System.out.println(Student.studentCount);  // 3

// studentCount принадлежит КЛАССУ Student, не объектам

Пример 2: Константы

public class MathConstants {
    static final double PI = 3.14159;        // константа
    static final double EULER = 2.71828;    // константа
    static final int MAX_USERS = 1000;      // константа
}

// Использование
System.out.println(MathConstants.PI);     // через класс
System.out.println(MathConstants.MAX_USERS);

Пример 3: Конфигурация

public class Config {
    static String DATABASE_URL = "jdbc:mysql://localhost:3306/mydb";
    static String API_KEY = "secret-key-123";
    static int TIMEOUT = 30000;
}

// Везде в приложении используется одна конфигурация
public class UserService {
    public void connect() {
        String url = Config.DATABASE_URL;  // одна для всех
        // ...
    }
}

public class OrderService {
    public void connect() {
        String url = Config.DATABASE_URL;  // та же самая
        // ...
    }
}

Отличие от нестатических

public class Example {
    // НЕСТАТИЧЕСКАЯ переменная
    private int instanceVar = 0;
    
    // СТАТИЧЕСКАЯ переменная
    static int classVar = 0;
}

Example obj1 = new Example();
Example obj2 = new Example();

obj1.instanceVar = 10;
obj2.instanceVar = 20;
System.out.println(obj1.instanceVar);  // 10 (разные значения)
System.out.println(obj2.instanceVar);  // 20

obj1.classVar = 100;
obj2.classVar = 200;
System.out.println(obj1.classVar);  // 200 (одно значение!)
System.out.println(obj2.classVar);  // 200
System.out.println(Example.classVar);  // 200

// classVar изменение в одном месте видно везде

Инициализация статических переменных

При загрузке класса

public class Logger {
    static {  // Статический блок инициализации
        System.out.println("Класс Logger загружен");
    }
    
    static String logFile = "app.log";
    static int logLevel = 2;
}

// Вывод при загрузке класса:
// "Класс Logger загружен"
// logFile и logLevel инициализированы

Порядок инициализации

public class Init {
    static int num = 5;  // 1. инициализация
    
    static {  // 2. статический блок
        System.out.println("Static block");
        num = 10;
    }
    
    public static void main(String[] args) {  // 3. main
        System.out.println(num);  // 10
    }
}

// Вывод:
// Static block
// 10

Частые ошибки

Ошибка 1: Обращение через объект

// НЕПРАВИЛЬНО (работает, но плохо)
student.studentCount++;  // выглядит как экземпляр

// ПРАВИЛЬНО
Student.studentCount++;  // понятно, что это статическое

Ошибка 2: Изменение в конструкторе

public class Counter {
    static int count = 0;
    
    public Counter() {
        count++;  // правильно — увеличить для ВСЕХ
    }
}

Counter c1 = new Counter();  // count = 1
Counter c2 = new Counter();  // count = 2
Counter c3 = new Counter();  // count = 3

Ошибка 3: Shared state (общее состояние)

// ПЛОХО: статическая переменная как shared state
public class BankAccount {
    static double balance = 0;  // ОПАСНО!
    
    public void deposit(double amount) {
        balance += amount;  // все счёта едят один баланс!
    }
}

// ПРАВИЛЬНО: каждый счёт свой
public class BankAccount {
    private double balance = 0;  // нестатическая
    
    public void deposit(double amount) {
        balance += amount;  // каждый счёт свой баланс
    }
}

Когда использовать

Используй статические переменные для:

✅ Счётчиков класса

static int totalObjects = 0;

✅ Констант

static final double PI = 3.14;

✅ Конфигурации

static String DATABASE_URL = "jdbc:mysql://...";

✅ Общего ресурса

static Logger logger = LoggerFactory.getLogger(MyClass.class);

НЕ используй для:

❌ Данных конкретного объекта

// НЕПРАВИЛЬНО
static String username = "John";  // какому объекту принадлежит?

// ПРАВИЛЬНО
private String username = "John";  // этому объекту

❌ Изменяемого состояния (особенно в многопоточной среде)

// ОПАСНО в многопоток
static List<String> cache = new ArrayList<>();  // race condition

Выводы

Статические переменные относятся к КЛАССУ, а не к объектам:

  1. Одна переменная на весь класс (не на каждый объект)
  2. Живут в Heap, но в статической памяти класса
  3. Обращаются через ClassName.variable
  4. Инициализируются при загрузке класса
  5. Используются для счётчиков, констант, конфигурации

Чтобы понять принадлежность — помни: static = class, non-static = instance.