Переменные экземпляра и статические переменные
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 15 из 87.
До сих пор каждое поле, которое мы создавали, принадлежало конкретному объекту. У каждого BankAccount есть свой собственный balance, а у каждого Product — свое собственное name. Это переменные экземпляра — они существуют отдельно для каждого экземпляра класса.
Но что, если вам нужны данные, которые являются общими для всех объектов? Вот здесь и пригодятся статические переменные (также называемые переменными класса). Статическая переменная принадлежит самому классу, а не какому-либо конкретному объекту.
public class Student {
private String name; // Переменная экземпляра — уникальна для каждого студента
private static int totalCount; // Статическая переменная — общая для всех студентов
public Student(String name) {
this.name = name;
totalCount++; // Увеличивает общий счетчик
}
public static int getTotalCount() {
return totalCount;
}
}Когда вы создаете нескольких студентов, у каждого из них есть свое собственное name, но все они разделяют одно и то же totalCount:
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
System.out.println(Student.getTotalCount()); // Вывод: 2Обратите внимание, как мы обращаемся к статической переменной через имя класса (Student.getTotalCount()), а не через объект. Это подчеркивает, что статические члены принадлежат классу, а не экземплярам.
Используйте переменные экземпляра для данных, которые различаются у разных объектов (например, имя студента). Используйте статические переменные для данных, которые должны быть общими (например, подсчет количества существующих объектов).
Задание
ЛегкоДавайте создадим систему инвентаризации Book, которая отслеживает как сведения об отдельных книгах, так и общее количество книг во всей вашей коллекции, используя переменные экземпляра и статические переменные.
Вы создадите два файла для организации своего кода:
Book.java: Создайте класс Book, который отслеживает информацию об отдельных книгах, а также ведет учет всех когда-либо созданных книг:- Переменная экземпляра
title(String) — уникальная для каждой книги - Переменная экземпляра
price(double) — уникальная для каждой книги - Статическая переменная
totalBooks(int) — общая для всех объектов Book, отслеживающая количество созданных книг - Конструктор, который принимает название и цену и увеличивает общий счетчик книг
- Геттер
getTitle()для названия - Геттер
getPrice()для цены - Статический метод
getTotalBooks(), который возвращает общее количество созданных книг
- Переменная экземпляра
Main.java: Создайте несколько объектов Book и продемонстрируйте, как статический счетчик отслеживает все экземпляры. Вы получите три названия книг и три цены в качестве входных данных. После создания всех трех книг выведите четыре строки:- Название и цену каждой книги в формате:
[title]: $[price](цена отформатирована до 2 знаков после запятой) - Общее количество книг, используя статический метод:
Total books: [count]
- Название и цену каждой книги в формате:
Вы получите шесть входных данных по порядку: title1, price1, title2, price2, title3, price3.
Не забудьте обращаться к статическому методу через имя класса (Book.getTotalBooks()), а не через экземпляр объекта. Для форматирования цен используйте String.format("%.2f", price).
Шпаргалка
Статическая переменная (также называемая переменной класса) принадлежит самому классу и является общей для всех экземпляров этого класса, в отличие от переменных экземпляра, которые уникальны для каждого объекта.
Объявите статическую переменную, используя ключевое слово static:
public class Student {
private String name; // Переменная экземпляра - уникальна для каждого студента
private static int totalCount; // Статическая переменная - общая для всех студентов
public Student(String name) {
this.name = name;
totalCount++; // Увеличивает общий счетчик
}
public static int getTotalCount() {
return totalCount;
}
}Обращайтесь к статическим переменным и методам через имя класса, а не через экземпляр объекта:
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
System.out.println(Student.getTotalCount()); // Вывод: 2Используйте переменные экземпляра для данных, которые различаются у разных объектов. Используйте статические переменные для данных, которые должны быть общими для всех экземпляров.
Попробуйте сами
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Считать входные данные для трех книг
String title1 = scanner.nextLine();
double price1 = Double.parseDouble(scanner.nextLine());
String title2 = scanner.nextLine();
double price2 = Double.parseDouble(scanner.nextLine());
String title3 = scanner.nextLine();
double price3 = Double.parseDouble(scanner.nextLine());
// TODO: Создать три объекта Book, используя входные данные выше
// TODO: Вывести название и цену каждой книги в формате: [title]: $[price]
// Использовать String.format("%.2f", price) для форматирования цены до 2 знаков после запятой
// TODO: Вывести общее количество книг, используя статический метод
// Формат: Total books: [count]
// Не забудьте обращаться к статическому методу через имя класса: Book.getTotalBooks()
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»