Статические переменные в Java - Вопросы
Всего: 7 вопросов
1. Что такое статическая переменная в Java?
Что такое статическая переменная в Java?
Статическая переменная (static-поле, переменная класса) — это поле, объявленное в классе с ключевым словом static, например static int b;. Она принадлежит самому классу, а не объектам: существует в единственном экземпляре на весь класс, создаётся один раз при загрузке и инициализации класса и доступна без создания объекта.
Если значение не задано явно, static-поле получает значение по умолчанию: 0 для числовых типов, false для boolean, null для ссылочных типов. Глобальной переменной в привычном смысле оно не является: поле всегда принадлежит конкретному классу, а его видимость ограничивается модификаторами доступа.
2. Чем статическая переменная отличается от обычной переменной объекта?
Чем статическая переменная отличается от обычной переменной объекта?
Обычная переменная (int a;) есть у каждого объекта своя, создаётся при new и доступна только через объект: obj.a. Из static-метода к ней можно обратиться только через ссылку на объект. Используется для состояния конкретного объекта (цвет, имя).
Статическая переменная (static int b;) одна на весь класс, создаётся один раз при загрузке и инициализации класса, к ней обращаются через имя класса: StaticVars.b, а из static-метода — напрямую. Типичное применение — счётчики, константы, общие настройки. Если изменить static-поле через один объект, новое значение будет видно через все остальные.
3. Как правильно обращаться к статической переменной и почему не стоит делать это через объект?
Как правильно обращаться к статической переменной и почему не стоит делать это через объект?
Из другого класса к статической переменной обращаются через имя класса: StaticVars.b. Внутри того же класса можно писать просто b. Часто используемые чужие константы можно подключить через static import.
Технически обращение через объект (staticVars1.b) тоже компилируется, но так делать не рекомендуется: читатель кода решит, что это поле конкретного объекта, а IDE выдаст предупреждение. Компилятор всё равно подставляет тип переменной, поэтому даже StaticVars s = null; s.b не выбросит NullPointerException.
4. Как с помощью статической переменной посчитать количество созданных объектов класса и какая здесь проблема в многопоточном коде?
Как с помощью статической переменной посчитать количество созданных объектов класса и какая здесь проблема в многопоточном коде?
В классе объявляют private static int count = 0; и увеличивают его в конструкторе (count++), так как конструктор вызывается при создании каждого объекта. Значение отдают через статический метод getCount(). У каждого объекта Ball свой color, но count общий, поэтому после двух new Ball(...) вызов Ball.getCount() вернёт 2.
Проблема: операция count++ не атомарна, а статическое поле видно из всех потоков. При одновременном создании объектов из нескольких потоков счётчик может «потерять» увеличения. В многопоточном коде используйте AtomicInteger или синхронизацию.
5. Как объявить константу в Java и есть ли в Java ключевое слово const?
Как объявить константу в Java и есть ли в Java ключевое слово const?
Константу объявляют сочетанием модификаторов static (одно значение на класс) и final (значение нельзя изменить после присваивания). Имя по соглашению пишут в верхнем регистре через подчёркивание: public static final int MAX_USERS = 100;. Попытка присвоить новое значение — ошибка компиляции.
Если константа примитивного типа или String инициализирована выражением, известным при компиляции, это compile-time константа: компилятор подставляет её значение в места использования, и её можно использовать в метках case. Слово const в Java зарезервировано, но не используется — объявить с ним переменную нельзя.
6. Чем static отличается от final и делает ли final ссылку неизменяемым объект?
Чем static отличается от final и делает ли final ссылку неизменяемым объект?
static определяет, кому принадлежит переменная: классу (одна копия) или объекту (своя копия у каждого). final определяет, можно ли её изменить после присваивания. Модификаторы независимы: бывают static-поля без final (счётчик), final-поля без static (неизменяемый id объекта) и их сочетание — константы.
final у ссылочной переменной запрещает менять только саму ссылку, но не содержимое объекта: для static final List<String> NAMES = new ArrayList<>(); вызов NAMES.add(...) допустим. Для по-настоящему неизменяемой коллекции используйте List.of(...).
7. Когда инициализируется статическая переменная и где она хранится в памяти?
Когда инициализируется статическая переменная и где она хранится в памяти?
Статическая переменная инициализируется один раз при инициализации класса — перед первым созданием объекта, первым вызовом статического метода или первым обращением к статическому полю (кроме compile-time констант). Инициализаторы static-полей и статические блоки выполняются в порядке объявления в классе.
Начиная с JDK 7 (HotSpot) значения статических полей хранятся в куче (heap) вместе с объектом Class своего класса; раньше они находились в PermGen. В Java 8 PermGen заменена на Metaspace, где хранятся метаданные классов, но не значения static-полей.