Назначение двух видов областей в Java

У меня возникают трудности с присвоением имен двум видам областей видимости, которые я вижу в Java:

class Fun {
    int f = 1;
    void fun() {
        int f = 2;
        while(true){
            int f = 3;
            int g = 1;
        }
        int g = 2;
    }
}

В основном это случай с f = 3 и g = 2;

Оператор

A while не вводит новую область видимости, поэтому я не могу создать локальную переменную while с именем f. Но если я создаю локальную переменную с именем g, тогда я смогу "заново создать" ее после цикла. Зачем? Я знаю, что он больше не доступен, но если компилятор проверяет доступность, он почти проверяет области действия.

Итак, мне было интересно, что это за сделка, что называются этими понятиями? Это то же самое, что и в С++?


Мне просто удалось установить g++ и сам пробовал:

#include <iostream>
using namespace std;

int main(){
    int f = 0;
    for(int i=0; i<1; i++){
        int f = 1;
        cout << f << endl;
        {
            int f = 2;
            cout << f << endl;
        }
    }
    cout << f << endl;
}

Поэтому, по-видимому, С++ одинаково относится ко всем областям!

Ответ 1

Как только вы покинули время, {} цикл g вышел из сферы действия, как только вы его покинули. Тогда было бы полезно снова объявить g.

Локальные переменные относятся только к области действия в течение всего блока, в котором они объявлены.

Подробнее:

  • Первый f - это область объекта. Его доступный из объекта вообще раз.
  • Второй f - это локальная область. Вы получаете доступ к нему с помощью f, вы все еще может получить доступ к области объектов f с помощью this.f.
  • Третий f пытается создать вторую локальную область f. Это неверно.

  • Первый g создает локальную область g.

  • Второй g создает вторую локальную область g, но первая из них уже вышла из области действия и исчезла.

Таким образом, единственным недопустимым объявлением является третий f.

Существует третий тип области действия, в которой объявляются статические переменные - это переменные, которые распределяются между каждым экземпляром класса.

Существует несколько имен для типов, некоторые из наиболее распространенных - локальные переменные, переменные экземпляра (также называемые полями) и переменные класса (также называемые статическими полями). У вас также есть параметры метода, но это другой способ получить локальную переменную.

Для дальнейшего чтения:

Ответ 2

В java запрещено изменять переменные из внешних локальных областей, IIRC. Это просто "произвольное" языковое правило, чтобы программист не совершал глупых ошибок. С# имеет такое же правило, IIRC или даже более строгое (последний g может быть ошибкой в ​​С#, потому что он был в рамках одного метода, но не уверен). C и С++ не имеют этого правила, хотя обычно есть предупреждение о компиляторе, в зависимости от флагов компилятора и предупреждения.

Каждый {} является новой областью блока.

Последний g не отбрасывает предыдущий g, потому что ранее он больше не находится в области видимости. Так что это нормально.

Самый внутренний f затеняет более ранний локальный f, который все еще находится в области видимости, поэтому не работает.

Элементы-члены класса по-прежнему доступны с помощью this., поэтому можно скрыть их (хотя они могут ввести в заблуждение, особенно если подсветка синтаксиса IDE не выделяет их по-разному).

Ответ 3

class Fun {
    int f = 1;// Its My f and i wont tell my fun() not to have 'f'
    void fun() {
        int f = 2; //Its my 'f' and till i own my 'f' i wont consider Fun Class 'f' also while 'f' 
        while(true){
            int f = 3; //Its my 'f' and he rules within me alone 
            int g = 1;
        }
        int g = 2;
    }
}

Ответ 4

Область объявления локальной переменной в блоке - это остальная часть блока, в котором отображается декларация (JLS 6.3 Scope of the Declaration).

void fun() {  // block starts

   int f = 2; // f will be visible everywhere from fun() body

...

   {  // another block starts, it legal even without while or for
      // f is visible, you cannot declare it again

      int g = 1; // will be visible till the end of the block

   }

   // g is invisible here because the block where it was declared ended
}