Переменные в Java
Объявляйте и инициализируйте переменные в Java, изучайте виды переменных (локальные, экземпляра, статические) и правила именования.
Переменная — это именованная ячейка памяти с фиксированным типом. После объявления тип изменить нельзя, но хранящееся значение, как правило, можно. Тип определяет, сколько памяти занимает переменная, какие значения допустимы и какие операции разрешает компилятор. В этой главе рассматривается, как объявлять и инициализировать переменные, какие четыре разновидности различает Java, а также правила использования final, var и области видимости.
Объявление переменной
Базовая форма — тип, затем имя и точка с запятой:
type name;Например, int score; резервирует слот типа int с именем score. Тип — один из встроенных типов Java (int, double, boolean, char, …) или любой класс или интерфейс — полный список см. в разделе Java Data Types.
Простейшие объявления:
int score;
String name;
boolean ready;Они резервируют память, но пока не помещают туда никакого значения.
Инициализация
Для присваивания значения используется =:
int score = 0;
String name = "Ada";
boolean ready = true;Можно также объявить и присвоить по отдельности:
int score;
score = 0;Или объявить несколько переменных одного типа сразу:
int x = 1, y = 2, z = 3;(Обычно нагляднее писать по одной переменной на строку.)
Локальные переменные должны быть присвоены перед использованием
Локальная переменная — объявленная внутри метода — не имеет значения по умолчанию. Компилятор запрещает её читать до тех пор, пока ей не будет что-то присвоено:
public static void main(String[] args) {
int x;
// System.out.println(x); // compile error: variable x might not have been initialized
x = 5;
System.out.println(x); // OK
}Это одна из самых полезных функций безопасности Java — она предотвращает целый класс ошибок, которые в других языках остались бы незамеченными.
Четыре разновидности переменных
Java различает четыре категории переменных по месту их объявления:
- Локальные переменные — объявляются внутри метода или блока. Существуют только во время выполнения метода. Значения по умолчанию нет. Перед использованием должны быть инициализированы.
- Переменные экземпляра (поля) — объявляются внутри класса, но вне методов. По одной копии на каждый объект. По умолчанию равны
0/0.0/false/null. - Статические переменные (переменные класса) — объявляются с ключевым словом
static. Одна копия, общая для всех экземпляров класса. По умолчанию равны0/false/null. - Параметры — объявляются в сигнатуре метода; получают значение, переданное вызывающим кодом.
public class Counter {
static int totalCounters; // static (class) variable
int count; // instance variable
public void add(int delta) { // delta is a parameter
int doubled = delta * 2; // doubled is a local variable
count += doubled;
}
}С переменными экземпляра и статическими переменными вы подробнее познакомитесь в главах об ООП; пока большинство переменных, с которыми вы будете работать, будут локальными.
final — присвоить один раз
Ключевое слово final перед объявлением делает переменную однократно присваиваемой. После первого присваивания изменить значение нельзя:
final int MAX_RETRIES = 3;
// MAX_RETRIES = 4; // compile error: cannot assign a value to final variableИспользование final для значений, которые не должны меняться, делает намерение явным и позволяет компилятору обнаруживать случайное переприсваивание. По соглашению, final-поля с фиксированными константами именуются в стиле UPPER_SNAKE_CASE (см. Java Naming Conventions).
Обратите внимание: final фиксирует ссылку, а не объект, на который она указывает. final-ссылку переназначить нельзя, но сам объект по-прежнему может изменяться:
final int[] nums = {1, 2, 3};
nums[0] = 99; // OK — the array contents change
// nums = new int[5]; // compile error — the reference is finalvar — пусть компилятор выведет тип
Начиная с Java 10, можно писать var вместо типа для локальных переменных, когда тип очевиден из правой части выражения:
var name = "Ada"; // inferred as String
var score = 0; // inferred as int
var values = new int[10]; // inferred as int[]var — это не динамическая типизация: переменная по-прежнему имеет фиксированный тип, просто компилятор определяет его сам. Ограничения:
- Только для локальных переменных.
- Правая часть должна присутствовать (
var x;недопустимо). - Нельзя использовать для параметров, переменных экземпляра и статических переменных.
var особенно удобен, когда имя типа длинное или очевидно из контекста:
var orders = new HashMap<String, List<Order>>();Используйте обычные объявления типов, когда выводимый тип может быть неочевиден читателю кода.
Область видимости
Переменная находится в области видимости — доступна — от места объявления до конца охватывающего блока:
public static void main(String[] args) {
int outer = 1;
if (outer > 0) {
int inner = 2;
System.out.println(outer + inner); // both visible
}
// System.out.println(inner); // compile error: inner is out of scope
}Нельзя объявить две локальные переменные с одинаковым именем в перекрывающихся областях видимости — но имя может использоваться повторно в двух отдельных, непересекающихся блоках:
for (int i = 0; i < 3; i++) { /* i lives here */ }
for (int i = 0; i < 5; i++) { /* a new, separate i */ } // fineХорошая практика — делать область видимости переменных как можно меньше: объявляйте каждую переменную как можно ближе к месту первого использования.
Рабочий пример
Что дальше
Раздел Java Naming Conventions охватывает стандартные правила именования классов, методов, переменных и констант, которым следуют все Java-проекты.