Область видимости переменных в Java
Разбираемся, что такое, как работает и в чем особенности использования.


vlada_maestro / shutterstock
Область видимости переменной — свойство, которое определяет, можно ли использовать переменную из разных областей класса. Это зависит от места, где переменная была объявлена.
Если какая-то переменная объявляется в теле метода, в цикле или условной конструкции, она исчезает после завершения работы этого метода, цикла или ветки. Это же касается и аргументов методов: переменные-аргументы существуют только в момент выполнения метода. А значит, они не могут быть доступны из других блоков кода.
Область видимости внутри метода
Рассмотрим пример кода метода main ():
public static void main(String[] args) {
int money = 150;
int priceCappuchino = 120;
int priceEspresso = 70;
if (money >= priceCappuchino) {
int change = money - priceCappuchino;
System.out.println("хватает на капучино, останется " + change + "р.");
}
if (money >= priceEspresso) {
int change = money - priceEspresso;
System.out.println("хватает на эспрессо, останется " + change + "р.");
}
}
В начале метода объявляются переменные money, priceCappuchino, priceEspresso, и инициализируются — устанавливается их значение.
Все три переменные доступны для использования в любой строке этого метода — начиная со строки объявления переменной и заканчивая закрывающейся } метода. Это позволяет использовать эти переменные в блоках if для расчёта суммы оставшихся денег.
Начало области видимости
Область видимости переменной начинается с момента объявления — использовать переменную до её объявления невозможно.
На скриншоте область видимости переменной money выделена зелёным цветом:

Рассмотрим переменные change внутри условных операторов if. Область видимости переменных ограничена {}, в которых они находятся. Это значит, что каждая из двух change работает только внутри своего блока if, а в следующем существует уже другая переменная, но с тем же именем.
Важно, что переменные change — это две совершенно разные переменные. Области видимости позволяют в непересекающихся блоках кода создавать и использовать переменные с одинаковыми именами.
Доступность переменной ограничена областью видимости
Переменная уничтожается после выхода из её области видимости, и далее к ней доступа нет.

При попытке использовать переменные за пределами цикла и скомпилировать код мы получим ошибку компиляции:
Main.java:23: error: cannot find symbol
System.out.println(change);
^
symbol: variable change
location: class Main
Область видимости аргументов метода — тело метода
В примере у метода main () один аргумент в виде массива String[] args. Его область видимости — всё тело метода.
Цикл for
Возьмём пример кода:
public static void main(String[] args) {
int money = 150;
int priceCappuchino = 120;
int priceEspresso = 70;
for (int i = 0; i <= money; i += 10) {
System.out.println("Заработано" + i + "р.");
if (i == priceEspresso) {
System.out.println("Можно пойти и выпить эспрессо!");
} else if (i == priceCappuchino) {
System.out.println("Заработано на капучино!");
}
}
}
В цикле объявляется и инициализируется переменная i, которая используется при проверке условия и увеличивается на 10 при каждой итерации.
Область видимости переменной i ограничена телом цикла for, то есть {} после условия цикла. Переменная i будет уничтожена после завершения цикла:

Область видимости переменных внутри класса
Внутри класса область видимости зависит от типа переменной:
- Статические переменные принадлежат самому классу. Они доступны без создания объекта, область их видимости содержит все методы класса — как статические, так и нет.
- Нестатические переменные класса принадлежат экземпляру класса (объекта). В их область видимости попадают нестатические методы класса.
Пример:
public class Car {
private static int totalFuelConsumption;
private int fuel = 86;
private int consumption;
//создаем объект с указанием расхода топлива
public Car(int consumption) {
this.consumption = consumption;
}
//метод, имитирующий проезд автомобилем заданного расстояния
public void drive(int km) {
int fuelRequired = km * consumption;
if (fuel >= fuelRequired) {
fuel -= fuelRequired;
totalFuelConsumption += fuelRequired;
System.out.printf("Автомобиль проехал %dкм, потрачено %dл топлива", km,
fuelRequired);
}
}
//получаем значение расхода на поездки всех объектов типа Car
public static int getTotalFuelConsumption() {
return totalFuelConsumption;
}
}
Разберём область видимости каждой из переменных:
- private static int totalFuelConsumption — статическая переменная используется в статическом методе getTotalFuelConsumption () и в нестатическом методе drive (int km). Область видимости здесь — весь класс.
- private int fuel = 86 — переменная нестатическая. А значит, она может использоваться только в конструкторах класса и его нестатических методах.
- private int consumption — переменная нестатическая. Значит, она может использоваться только в конструкторах класса и его нестатических методах.
Ключевое слово this
Если посмотреть на конструктор класса Car, то переменная, которую передают в аргументе конструктора, названа таким же именем, как и параметр класса. В этом случае области видимости переменной consumption класса и аргумента конструктора consumption пересекаются. По умолчанию используется переменная с более узкой областью видимости, то есть аргумент метода. Чтобы использовать переменную класса, необходимо на неё явно указать с помощью ключевого слова this.
- int fuelRequired объявлена в методе drive (). Область видимости ограничена этим методом, использовать в других методах класса невозможно.