Статические поля и методы
Обычное поле есть у каждого объекта своё. Но иногда данные относятся ко всему классу сразу: например, счётчик созданных объектов или постоянная величина. Для этого служит ключевое слово static.
Статическое поле
Поле с модификатором static существует в одном экземпляре на весь класс. Все объекты видят и меняют одно и то же значение:
class User {
static int count = 0;
String name;
User(String name) {
this.name = name;
count++;
}
}
void main() {
new User("Анна");
new User("Олег");
IO.println(User.count);
}Результат:
2К статическому полю обращаются через имя класса: User.count. Объект для этого не нужен.
Статический метод
Статический метод тоже принадлежит классу, а не объекту. Его вызывают через имя класса. Так устроены вспомогательные методы, которым не нужны данные конкретного объекта:
class Prices {
static double withTax(double price) {
return price * 1.2;
}
}
void main() {
IO.println(Prices.withTax(50));
}Результат:
60.0Вы уже пользовались такими методами: Math.max(), Integer.parseInt() и String.valueOf() — статические.
Константы
Сочетание static final даёт константу — одно значение на класс, которое нельзя изменить. Имена констант по соглашению пишут заглавными буквами через подчёркивание:
class Shop {
static final int MAX_ITEMS = 10;
static final String CURRENCY = "€";
}
void main() {
IO.println("Не больше " + Shop.MAX_ITEMS + " товаров");
IO.println("Валюта: " + Shop.CURRENCY);
}Результат:
Не больше 10 товаров
Валюта: €Статическое и обычное вместе
Обычный метод может пользоваться статическими полями, потому что у класса они всегда есть. Здесь каждый билет получает номер из общего счётчика:
class Ticket {
static int nextNumber = 1;
int number;
Ticket() {
number = nextNumber;
nextNumber++;
}
}
void main() {
Ticket a = new Ticket();
Ticket b = new Ticket();
IO.println(a.number + " и " + b.number);
}Результат:
1 и 2Когда использовать static
Делайте поле или метод статическим, когда он не зависит от конкретного объекта: константы, счётчики, вспомогательные вычисления. Данные, которые у каждого объекта свои, должны оставаться обычными полями. Слишком много static превращает классы в набор глобальных переменных, и программу становится трудно менять.
Частая ошибка
Статический метод вызывается без объекта, поэтому в нём нет this и недоступны обычные поля. Обращение к ним не компилируется:
class User {
String name;
static void show() {
IO.println(name);
}
}
void main() {
User.show();
}Результат:
Main.java:5: error: non-static variable name cannot be referenced from a static context
IO.println(name);
^Либо сделайте метод обычным и вызывайте его у объекта, либо передайте нужное значение параметром.