JavaRush /Курсы /Java Syntax /Еще об области действия переменных

Еще об области действия переменных

Java Syntax
4 уровень , 1 лекция
Открыта

— Профессор всё свою линию гнёт. Все они, старые лекторишки, такие. Всё, что он может рассказать, ты можешь прочесть в книгах. Запомни, ещё ни один человек не научился плавать, прослушав с десяток лекций по этому поводу. Лекции помогают, когда ты 100% в теме и знаешь сам чуть меньше этого профессора.

— Ну, от лекций профессора же есть польза.

— Ага… вернее, мы надеемся, что она есть. Чем больше точек зрения на один и тот же материал ты услышишь, тем больше задумаешься, а как же дела обстоят на самом деле. Услышав только одну точку зрения, ты либо веришь ей, либо нет. Ладно, давай перейдём к делу.

— Давай рассмотрим картинку, которую я уже давал тебе ранее:


public class Variables

{
   private static String TEXT = "The end.";
  ┗━━━━━━━━━━━━━━┛
   public static void main (String[] args)
                          ┗━━━━━━━┛
  {
     System.out.println("Hi");
     String s = "Hi!";
   ┏┗━━━━┛
    System.out.println(s);
    if (args != null)
    {
       String s2 = s;
      ┗━━━━┛    
      System.out.println(s2);
     
    }
    Variables variables = new Variables();
    System.out.println(variables.classVariables);
    System.out.println(TEXT);
   
  }
 
   public String classVariables;
  ┗━━━━━━━━━━━━━━━┛
   public Variables()
   {
      classVariables = "Class Variables test.";
   }
}

1. Переменная, объявленная в методе, существует/видна с начала объявления до конца метода.

2. Переменная, объявленная в блоке кода, существует до конца этого блока кода.

3. Переменные — аргументы метода — существуют до конца выхода из метода.

4. Переменные класса/объекта существуют все время жизни содержащего их объекта. Их видимость регулируется специальными модификаторами доступа.

5. Статические переменные классов существуют все время работы программы. Их видимость также определяется модификаторами доступа.

— Да, помню эту картинку.

— Вот и отлично. Давай напомню тебе некоторые моменты.

— Все переменные, объявленные внутри методов, существуют/видны с начала их объявления до конца метода (пример: 1).

— Если переменная определена/объявлена в каком-то блоке кода, то она существует до конца этого блока кода (пример: 2).

— Если переменная является аргументом функции, то она существует/видна во всем теле данного метода (пример: 3) .

— Если переменная является переменной класса (пример: 4), то она привязана к конкретному объекту и существует все время, пока существует объект данного класса. Если нет ни одного объекта, то нет и ни одной копии переменной. К переменной можно обращаться (переменная видна) из всех методов класса, независимо от того, объявлены они до неё или после неё. Для каждого объекта создаётся своя, независимая от других объектов, переменная. Доступ к переменной невозможен из статических методов.

— Если переменная объявлена статической – помечена ключевым словом static, то она существует все время, когда существует её класс. Обычно JVM загружает класс в память при первом его использовании, тогда же и инициализируются статические переменные.

Еще об области действия переменных - 1

— В примере выше у нас объявлен класс Cat, у которого есть 4 переменные: a,b,s – обычные, а count – статическая. Если создать несколько объектов такого класса (например, 3 шт.), то каждый из них будет содержать свою собственную копию обычных переменных класса. Статическая же переменная – общая на всех. Формально она даже не находится внутри этих объектов, т.к. существует даже тогда, когда ни одного объекта класса Cat создано не было.

— Вот что произойдет, если мы объявим переменную s статической:

Еще об области действия переменных - 2

— Ага. Вроде понятно.

— А можно объявить одинаковые переменные?

— В методе — нет. Все переменные, объявленные внутри метода, должны иметь уникальные имена. Аргументы метода также считаются его переменными.

— А как насчёт переменных класса?

— Переменные класса тоже должны быть уникальными в рамках каждого конкретного класса.

Но есть исключение – имена переменных метода и переменных класса могут совпадать.

— А если мы в коде изменяем переменную, а таких переменных две, какая будет изменяться?

— Если в методе видны (доступны) несколько переменных, например, переменная класса и переменная метода, то тогда обращение произойдет к переменной метода.

Пример с двумя переменными count
class Main
{
    public int count = 0;     //объявили переменную класса

    public void run()
    {
        count = 15;           //обращение к переменной класса
        int count = 10;       //объявили локальную переменную метода
        count++;             //обращение к переменной метода
    }
}

— В этом коде объявлены две переменных count. В строке 3 объявлена переменная класса, а в строке 8 – переменная метода.

— Когда метод run будет исполняться, то произойдет вот что:

— В строке 7 мы обращаемся к переменной класса и присваиваем ей значение 15

— В строке 8 объявляется (создается) новая переменная методаcount. Она закрывает собой переменную класса. Любой дальнейший код в методе будет видеть (обращаться) именно к переменной метода.

— Понятно.

— Переменная метода закрывает собой переменную класса. Т.е. обращение будет происходить к переменной метода. Но к переменной класса тоже можно обратиться, только более сложным способом.

Статическая переменная класса
ClassName.variableName

Примеры:
Cat.catsCount
Обычная переменная класса
this.variableName

Примеры:
this.catsCount

— А что ещё за статические методы и статические переменные?

— Статические методы и переменные привязаны не к объектам класса, а непосредственно к самому классу. Т.е. если мы создадим 10 объектов класса Variables из примера в самом начале уровня, у нас будет 10 переменных classVariable (по одной на каждый объект) и всего одна общая переменная TEXT.

— У меня тут вопрос.

— А чем отличаются статические и нестатические методы?

— Давай рассмотрим, как работает обычный нестатический метод:

Как выглядит код
Cat cat = new Cat();
String name = cat.getName();
cat.setAge(17);
cat.setChildren(cat1, cat2, cat3);
Что происходит на самом деле
Cat cat = new Cat();
String name = Cat.getName(cat);
Cat.setAge(cat,17);
Cat.setChildren(cat, cat1, cat2, cat3);

— При вызове метода в виде «объект» точка «имя метода», на самом деле вызывается метод класса, в который первым аргументом передаётся тот самый объект. Внутри метода он получает имя this. Именно с ним и его данными происходят все действия.

— Нифига себе. Так вот как, оказывается, оно все работает!

— А вот как работает статический метод:

Как выглядит код
Cat cat1 = new Cat();
Cat cat2 = new Cat();
int catCount = Cat.getAllCatsCount();
Что происходит на самом деле
Cat cat1 = new Cat();
Cat cat2 = new Cat();
int catCount = Cat.getAllCatsCount(null);

— При вызове статического метода, никакого объекта внутрь не передаётся. Т.е. this равен null, поэтому статический метод не имеет доступа к нестатическим переменным и методам (ему нечего передать в такие методы в качестве this).

— Хм. Вроде понятно. Хотя как-то поверхностно.

— А вот и дядя Диего… С его задачками.

Комментарии (851)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Alexey Nikolaev Уровень 4
11 мая 2025
В задаче "Мне не подходит этот возраст…" демонстрируется видимость переменных в Java. В классе Person есть поле age, которое является членом класса и имеет публичный доступ (public). Это означает, что оно может быть использовано из любого места в программе. В методе adjustAge(int age) параметр age имеет то же имя, что и поле age. В этом случае, использование ключевого слова this.age позволяет различать между локальной переменной и полем класса. Локальная переменная age передается в метод как аргумент, а this.age ссылается на поле класса. Таким образом, внутри метода adjustAge(int age): age — это локальная переменная, которая скрывает поле класса с тем же именем. this.age — это поле класса Person.

public static class Person {
    public int age = 20;

    public void adjustAge(int age) {
        this.age = age + 20;
        System.out.println("Age in adjustAge() is: " + age);
    }
}
В этом коде: this.age обновляет поле класса, добавляя к нему 20. Локальная переменная age используется для вывода значения перед его изменением. Таким образом, видимость переменных в Java позволяет различать между локальными и членами класса с помощью ключевого слова this. Какое значение имеет локальная переменная age в момент инициализации?

public void adjustAge(int age) {
В момент инициализации локальной переменной age в методе adjustAge(int age) она принимает значение, переданное в качестве аргумента при вызове этого метода. В данном случае, когда в main вызывается person.adjustAge(person.age);, локальная переменная age инициализируется значением поля age объекта person, которое равно 20. Таким образом, значение локальной переменной age в момент инициализации — это то значение, которое было передано в метод. В данном примере это значение равно 20.
Виктор Уровень 11
12 февраля 2025
Задачка решена, читайте внимательно статью и пробуйте - «Переменные — аргументы метода — существуют до конца выхода из метода.»
Egor Bulkov Уровень 6
30 января 2025
Пошел читать Герберта Шилдта, пока ничего не ясно ((
vlafriday Уровень 1
2 мая 2024
02.05.2024 check, мой уровень 4
Сэсэг Доржиева Уровень 8
7 июня 2023
Я потеряла смысл слова apple
YouSSR Уровень 14
30 мая 2023
Прочитал. Разобрался. Решил. Но явно что забуду через недельку. Вы не думали что для лекций не помешали бы закладки, на случай если надо что-то быстро повторить?
Anonymous #3283984 Уровень 24
3 апреля 2023
Первую задачку решил только исходя из своего опыта предыдущих курсов по JS, та была такая тема как контекст вызова в замыкании. Получается что когда идет присваивание age = age + 20, то присвоение не присваивается обьекту Person, тк у age не ссылается на него с помощью ключевого слова this.!!!
Basilius Уровень 33
21 марта 2023
А мне нравится как тут поставлены задачи. Материала всегда достаточно, как минимум для того, чтобы понимать в какую сторону искать. От части ведь есть кайф в том, чтобы найти способ решения задачи самому. Плюс так лучше усваивается материал. Ну Java это не столик из икеа, чтобы было просто любую программку собрать за 10 минут)) Так что терпения и держите огнетушитель недалеко, чтобы вовремя тушить стул)
Даниил Синицын Уровень 12
10 марта 2023
Почитал коменты - солидарен со всеми, кто говорит что непонятно. Реально, объяснение очень непонятное. В свое время начинал изучать Java только по этому порталу. Помню, этот урок никак мне не давался. Потом какое то время сюда не заходил. Но немного практиковался с Java на других ресурсах. Только когда пришло понимание ООП - данный урок стал понятен. Без этого очень сложно уловить суть. Так что я могу предложить обучающимся особо не зацикливаться на данном уроке, если вы не изучали другие ресурсы - данных до этого знаний недостаточно, чтобы понять всю концепцию. Она станет ясной ближе к 10 уровню. Я бы сейчас, конечно, объяснял по другому. Т.к. Java рассчитана на ООП, то в ней под это многое заточено. Но есть и возможность писать программы без ООП. Именно поэтому в ней так много разных многословных модификаторов. Если сделать статическую переменную класса (модификатор static), то ее можно будет использовать сразу без ООП, по факту написания в классе. То же самое относится и к статическим методам (или как тут их еще называют - функциям). К такой переменной всегда можно обратиться через вызов: Название_класса.Название_переменной. Если модификатора static нет, то такая переменная как бы не существует, хотя и объявлена, до момента создания объекта. Она появляется в момент создания объекта. Именно тогда, когда мы пишем: Имя_Класса Имя_объекта = new Имя_Класса() - как тут и приводится в примере про кошку. После этого к ней уже можно обратиться. Если обращаемся извне, то надо писать так: Имя_Объекта.Имя_Переменной. Если хотим обратиться к ней из кода объекта, к примеру из какой то процедуры. Как в уроке - из процедуры run(), то надо писать так: this.Имя_переменной. В примере урока - переменная count в методе после создания перекрывает переменную класса. Но мы по прежнему можем обратиться к переменной класса через вызов: this.count
hatah Уровень 6
10 марта 2023
Спасибо
Евгений Уровень 3 Expert
18 апреля 2023
Інформативне пояснення, дякую.
23 февраля 2023
Совершенно непонятное объяснение. Конечно, задачу я решил благодаря постам. На мой взгляд объяснение ДО задачи должно быть хоть как-то связанно с задачей. И лучше текст перечитать т.к. там ошибки в верстке, в т.ч. таблицы неправильно помещены в тексте.