Ключевое слово static в Java: объяснение и примеры. Практические Задания
Типичная ошибка новичка: в класс добавляют поле int count и увеличивают его в конструкторе. После трёх вызовов new каждый объект показывает count == 1, потому что без static у каждого объекта своя копия счётчика. Задачи ниже как раз про то, как этого избежать.
Ключевое слово static в Java делает переменную или метод принадлежащими классу, а не отдельному объекту. Статическая переменная существует в одном экземпляре на весь класс, её значение видят все объекты. Поэтому её используют для счётчиков созданных объектов, общих сумм и констант.
На этой странице две практические задачи на static, наследование и абстрактные классы: цветочный магазин со счётчиком проданных цветов и фруктовая лавка с расчётом стоимости покупок. К каждой задаче есть готовое решение.
Что нужно знать перед решением
Самый частый пример использования static — подсчёт количества созданных объектов класса. Статический счётчик увеличивается в конструкторе и общий для всех экземпляров:
public class Flower {
private static int count = 0; // одна копия на весь класс
public Flower() {
count++;
}
public static int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
new Flower();
new Flower();
new Flower();
System.out.println(Flower.getCount()); // 3
}
} Чем статическая переменная отличается от обычной переменной экземпляра:
| Характеристика | Переменная экземпляра | Статическая переменная (static) |
|---|---|---|
| Кому принадлежит | Конкретному объекту | Классу целиком |
| Сколько копий | По одной в каждом объекте | Одна на класс (и на все его подклассы) |
| Как обращаться | obj.field | ClassName.field |
| Типичное применение | Состояние объекта: цена, вес, страна | Счётчики объектов, общие суммы, константы |
Задача 1. Цветочный магазин: счётчик проданных цветов
- Создать класс
Flowerс переменными: страна-производитель, срок хранения в днях, цена. - Создать классы, расширяющие
Flower: например, розы, гвоздики, тюльпаны и ещё один вид цветов на ваш выбор. - Собрать 3 букета (используем массив) и посчитать стоимость каждого. В букет могут входить цветы разных типов.
- Подсчитать общее количество проданных цветов, то есть всех цветов во всех собранных букетах (используем статическую переменную).
Подсказка: статическая переменная, объявленная в Flower, одна на весь класс и на все его подклассы. Если увеличивать её в конструкторе Flower, в счётчик попадут и розы, и тюльпаны, и гвоздики.
Задача 2. Фруктовая лавка: абстрактный класс и стоимость покупок
- Создать абстрактный класс
Фрукти классыЯблоко,Груша,Абрикос, расширяющие его. - Класс
Фруктсодержит:
а) переменную вес;
б) завершённый методprintManufacturerInfo():
в) абстрактный метод, возвращающий стоимость фрукта с учётом его веса. Метод нужно переопределить в каждом классе-наследнике.public void printManufacturerInfo() { System.out.print("Made in Ukraine"); } - Создать несколько объектов разных классов.
- Подсчитать общую стоимость всех проданных фруктов.
- Отдельно подсчитать общую стоимость проданных яблок, груш и абрикосов.
Подсказка: общую сумму и суммы по каждому виду фруктов удобно накапливать в статических переменных. Общую сумму храните в Фрукт, а суммы по видам — в классах-наследниках.
Об именах классов
Java допускает кириллицу в идентификаторах, поэтому Фрукт и Яблоко скомпилируются. В реальных проектах так не пишут: классы называют по-английски (Fruit, Apple, Pear, Apricot). Советуем сразу делать так же.
На чём чаще всего ошибаются
- Счётчик без
static. Каждый новый объект получает собственную копию поля, начинающуюся с 0, конструктор увеличивает её один раз, поэтому каждый объект показывает 1. - Счётчик в каждом подклассе вместо базового. Если нужно общее количество цветов, счётчик должен лежать в
Flower. Отдельные счётчики вRoseилиTulipдадут только количество по видам. - Обращение к статическому полю через объект. Если поле доступно, запись
rose.countкомпилируется, но вводит в заблуждение: она выглядит как состояние конкретного объекта, и IDE выдаёт предупреждение. Обращайтесь через имя класса:Flower.countилиFlower.getCount(). - Использование
thisв статическом методе. У статического метода нет текущего объекта, поэтомуthisи нестатические поля в нём недоступны.
Перед отправкой решения сверьтесь с рекомендациями по оформлению кода на Java.
Часто задаваемые вопросы
Можно ли обратиться к нестатической переменной из статического метода?
Напрямую нельзя: статический метод вызывается без объекта, поэтому у него нет this. Код не скомпилируется с ошибкой «non-static variable cannot be referenced from a static context». Чтобы прочитать поле экземпляра, сначала создайте объект или передайте его в метод как параметр.
Можно ли переопределить статический метод в Java?
Нет. Статический метод с той же сигнатурой в подклассе не переопределяет, а скрывает метод родителя (method hiding). Какой метод вызовется, решает тип ссылки на этапе компиляции, а не реальный тип объекта, поэтому полиморфизм для static-методов не работает.
Общая ли статическая переменная родителя для всех подклассов?
Да. Статическое поле, объявленное в Flower, существует в одном экземпляре, и все подклассы (Rose, Tulip и другие) работают с этой же копией. Отдельная копия появится, только если в подклассе объявить своё поле с тем же именем, но так делать не стоит: получится сокрытие поля и путаница.
Потокобезопасен ли счётчик static int count с count++?
Нет. Операция count++ не атомарна, и при одновременном создании объектов из нескольких потоков часть увеличений может потеряться. Для учебных задач это не важно. В многопоточном коде используйте AtomicInteger или синхронизацию.
Комментарии