Значения по умолчанию
Что лежит в коробке, в которую ещё ничего не положили? В первом уроке темы компилятор не дал прочитать такую переменную внутри main. Но у переменных, объявленных прямо в классе, ответ другой.
Представьте две коробки. Одну вы завели сами и пока ничего в неё не положили, поэтому заглядывать в неё компилятор не разрешает. Другую заранее приготовил склад, и в ней уже лежит стандартная вещь: ноль, false или пометка «ничего». Посмотрим на вторую коробку в деле:
public class Main {
static int count;
static double price;
static boolean ready;
static String name;
public static void main(String[] args) {
System.out.println(count); // 0
System.out.println(price); // 0.0
System.out.println(ready); // false
System.out.println(name); // null
}
}Программа компилируется и печатает четыре значения, хотя ни одной из четырёх переменных значение не задали.
Поля и значения по умолчанию
Переменную, объявленную прямо в классе, вне main, называют полем. Слово static перед ним — как у main: поле принадлежит самому классу. Константа вроде static final int MAX_SPEED = 120; — тоже поле, только её значение задано сразу и не меняется.
Поле без значения получает значение по умолчанию своего типа:
| Тип поля | Значение по умолчанию |
|---|---|
byte, short, int, long | 0 |
float, double | 0.0 |
char | символ с кодом 0, '\u0000' |
boolean | false |
String | null |
Давайте разберём вывод программы:
countпечатается как0, как любое целое поле без значения.priceпечатается как0.0, с точкой, потому что этоdouble.readyпечатается какfalse.nameпечатается какnull.
null — особое значение «ничего». Это не пустая строка: строки в поле name нет вовсе, и println сообщает об этом словом null.
Здесь картинка с коробкой неточна. Пустая коробка в жизни — это «ничего». А поле типа int не пусто: в нём лежит настоящее число 0, и с ним можно работать, как с любым другим.
Локальные переменные
Переменную, объявленную внутри main или другого метода, называют локальной. Значения по умолчанию она не получает. Сравним поле и локальную переменную в одной программе:
public class Main {
static int total;
public static void main(String[] args) {
int local;
System.out.println(total); // 0
local = 7;
System.out.println(local); // 7
}
}Разберём по строкам:
static int total;объявляет поле, и в нём сразу лежит0.int local;объявляет локальную переменную без значения.System.out.println(total)печатает0: поле можно читать сразу.local = 7;кладёт значение в локальную переменную.System.out.println(local)печатает7. Без строкиlocal = 7;программа бы не скомпилировалась.
Почему поле получает значение само, а локальная переменная — нет? Это частый вопрос на собеседовании. Ответ такой:
- локальную переменную видно только внутри её метода, поэтому компилятор может проверить каждое чтение и поймать забытое значение ещё до запуска;
- поле могут читать разные методы класса в любом порядке, поэтому JVM сама кладёт в каждое поле значение по умолчанию, когда загружает класс.
Частая ошибка
Поле объявили без static:
public class Main {
int count;
public static void main(String[] args) {
System.out.println(count); // ✗
}
}error: non-static variable count cannot be referenced from a static contextПрограмма не компилируется. Поле без static принадлежит не классу, а объекту — отдельной вещи, которую программа создаёт по описанию класса уже во время работы. В этой программе объектов никто не создавал, и main работает без них, поэтому прочитать такое поле не может. Пока пишите у полей static, как у самого main: static int count;.
Главное
- Поле — переменная, объявленная в классе вне
main; без значения оно получает значение по умолчанию:0,0.0,falseилиnull. - Локальная переменная значения по умолчанию не получает, и компилятор не даст прочитать её до первого присваивания.
nullв поле типаStringзначит, что строки там нет.- Поле, которое читает
main, объявляют со словомstatic.