Область видимости переменных в Java

Область видимости (scope) определяет, в какой части программы переменная видна и может использоваться. В Java область видимости задаётся фигурными скобками { }: переменная существует от места объявления до закрывающей скобки своего блока.

В Java различают три основных вида переменных по области видимости: локальные (объявлены внутри метода или блока), поля экземпляра (поля объекта класса) и статические поля (общие для всего класса). Понимание scope — основа предсказуемого поведения программы и защита от трудноуловимых ошибок.

Синтаксис

public class Example {
    static int classField;     // статическое поле
    int instanceField;         // поле экземпляра

    void method() {
        int local = 10;        // локальная переменная
        {
            int blockVar = 5;  // переменная блока
        }
        // blockVar здесь уже не видна
    }
}

Пример 1. Локальная переменная

public class LocalScope {
    public static void main(String[] args) {
        int sensorValue = 512;
        System.out.println("Значение датчика: " + sensorValue);
    }
}

Вывод:

Значение датчика: 512

Пример 2. Область блока

public class BlockScope {
    public static void main(String[] args) {
        int pin = 13;
        {
            int delay = 1000;
            System.out.println("Пин " + pin + ", задержка " + delay);
        }
        // delay уже недоступна за пределами блока
        System.out.println("Пин " + pin);
    }
}

Вывод:

Пин 13, задержка 1000
Пин 13

Пример 3. Поле экземпляра против локальной

public class Robot {
    int speed = 100; // поле экземпляра

    void show() {
        int speed = 200; // локальная "затеняет" поле
        System.out.println("local speed = " + speed);
        System.out.println("field speed = " + this.speed);
    }

    public static void main(String[] args) {
        new Robot().show();
    }
}

Вывод:

local speed = 200
field speed = 100

Пример 4. Статическое поле

public class Counter {
    static int count = 0;

    static void tick() {
        count++;
    }

    public static void main(String[] args) {
        tick();
        tick();
        tick();
        System.out.println("count = " + count);
    }
}

Вывод:

count = 3

Пример 5. Переменная цикла

public class LoopScope {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            System.out.println("LED " + i + " моргнул");
        }
        // i здесь уже не существует
    }
}

Вывод:

LED 0 моргнул
LED 1 моргнул
LED 2 моргнул

Пример 6. Параметры метода

public class Params {
    static int square(int x) {
        return x * x;
    }

    public static void main(String[] args) {
        int result = square(7);
        System.out.println("7^2 = " + result);
    }
}

Вывод:

7^2 = 49

Подводные камни

  • Тень имени (shadowing). Локальная переменная с тем же именем, что и поле класса, перекрывает поле; чтобы обратиться к полю, используйте this.имя.

  • Использование до инициализации. Локальные переменные в Java не имеют значения по умолчанию — компилятор не даст использовать неинициализированную локальную переменную.

  • Объявление в цикле. Объявление переменной внутри for ограничивает её область телом цикла — не пытайтесь использовать счётчик после цикла.

  • Дублирование имени в одном блоке. Нельзя объявить две локальные переменные с одинаковым именем в одной области видимости.

См. также

Примечание

Лицензия и источники

Концепция описана на основе официального Java Tutorial от Oracle (https://docs.oracle.com/javase/tutorial/), Oracle Free Documentation License. Перевод, примеры и пояснения — © AlashEd Wiki.