Локальная переменная в теле цикла

91
09 августа 2019, 17:30

На различных специализированных интернет-ресурсах бытует множество мнений по этому вопросу. Порой эти мнения диаметрально отличаются друг от друга. К примеру, есть целый пласт практикующих специалистов, которые крайне не рекомендуют так делать (в основном из сообщества программистов, которые работают с языком C/C++). Другие же ратуют за то, чтобы переменные объявлялись настолько "локально", насколько это вообще возможно. Какая практика, на Ваш взгляд, является более оправданной?

Двигаемся дальше... Мне бы хотелось понять, что происходит со стеком, когда мы декларируем переменную в цикле. Правильно ли я понимаю, что после каждой пройденной итерации, те локальные переменные, которые были объявлены непосредственно в теле самого цикла, проходят через процесс удаления из стека (выполняется операция pop), а потом снова туда загружаются (это происходит уже в процессе новой итерации, в этом случае срабатывает операция push)? Не уверен, что это так, но на такие размышления меня навёл следующий тестовый код:

class Test {
    public static void main(String[] args) {
        for(int i = 0; i < 5; i++) {
            if(i == 1)
                System.out.println(j);
            int j = 0;
        }
    }
}
/*
    Compilation Errors Detected
    Line: 6
    cannot find symbol
      symbol:   variable j
      location: class Test
*/

Как мы можем видеть, компилятор указывает нам на то, что в пределах области видимости, в которой мы пытаемся получить доступ к нашей локальной переменной, собственно отсутствует переменная с таким идентификатором (хотя мы её уже объявляли в предыдущей итерации). Что меня ещё смущает так это то, что если взглянуть на байт-код в случае, если переменная будет указана вне цикла (но будет использоваться в нём) и аналогичный бинарный код для той ситуации, когда объявление проходило в цикле, то выяснится, что они абсолютно одинаковы!

Теперь ключевой вопрос. Учитывая всё вышенаписанное, что же происходит на самом деле?

Answer 1

Память под стек выделяется один раз. Компилятор расчитывает максимально необходимую память и выделяет столько сколько надо.

void foo() {
   if(condition1) {
       int i = 1;
   }
   if(condition2) {
       int j = 2;
   }
}

В этом примере на стеке будет выделена память только для одной переменной.

Операция pop (точнее ее аналог) вызывается только один раз при выходе из метода.

Ваш пример с ошибкой компиляции объясняется тем что компилятор гарантирует то что локальные переменные будут проинициализированны.

READ ALSO
Генерация случайного числа от a до b

Генерация случайного числа от a до b

Сделал вот такМожно ли сделать решение проще и корректно ли моё решение?

100
Spring security - Request method &#39;POST&#39; not supported

Spring security - Request method 'POST' not supported

Ошибка вылетает при попытке залогинится

96
Как сделать окно сохранения данных с русскими кнопками в java?

Как сделать окно сохранения данных с русскими кнопками в java?

У меня проект на java, я сделал опцию сохранения данных через JFileChooserНачальство мне высказало замечание, дескать, проект под русскоязычного...

151