Ключевое слово static
static привязывает член к классу, а не к конкретному экземпляру. Одно статическое поле существует на пару «класс + загрузчик класса», поэтому в приложении с несколькими ClassLoader копий может быть несколько.
final class RequestIds {
private static final AtomicLong SEQUENCE = new AtomicLong();
private RequestIds() {
}
static long next() {
return SEQUENCE.incrementAndGet();
}
}Где применяется
| Место | Смысл |
|---|---|
| поле | состояние класса, общее для его экземпляров |
| метод | вызов не требует объекта; нет this и super |
| вложенный класс | не хранит скрытую ссылку на внешний экземпляр |
| блок | выполняется при инициализации класса |
Статический метод выбирается по типу ссылки, а не динамическому типу объекта: это сокрытие, не полиморфное переопределение.
class Parent {
static String name() { return "parent"; }
}
class Child extends Parent {
static String name() { return "child"; }
}
Parent value = new Child();
System.out.println(value.name()); // parentИнициализация
Статические поля и блоки выполняются один раз в текстовом порядке при инициализации класса. До них поля имеют значения по умолчанию. Чтение compile-time константы вроде static final int LIMIT = 10 может не инициировать класс.
Ограничения и ошибки
- изменяемое
static-состояние требует потокобезопасности; - глобальная зависимость усложняет тестирование и жизненный цикл;
static final Listозначает неизменяемую ссылку, а не список;- нестатический внутренний класс нельзя создать без внешнего объекта;
mainстатический, потому что JVM должна вызвать его до создания экземпляра.
На собеседовании
Можно ли обратиться к нестатическому полю из static-метода? Только через явную ссылку на объект.
Переопределяются ли статические методы? Нет, они скрываются.
Сколько экземпляров статического поля? По одному на определение класса в каждом загрузчике.
Когда выполняется static-блок? При инициализации класса, не обязательно при его загрузке.
Связано: Блоки инициализации, Class loader, Можно ли вставить бин в статическое поле.