Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Вопрос Как понять как работает for() в джава?

Ну смотри оператор FOR это синтаксическая композиция для улучшения читаемости кода
Сам по себе является обычный цыклои WHILE но имеет иную структуру (инициализация; условие; действие)
На уровне JVM он не существует как конструкция, а при компиляции декомпозируется в набор независимых фрагментов управления потоком, связанных условными и безусловными переходами байткода.

1. Инициализация создает обычные локальные переменные в Local Variable Table
2. Условие это обычные компараторы по типу if_icmpge, if_icmpne, if_icmplt, if_icmpgt, if_icmple, if_icmpge все они нешают нужно ли повторять логику или нет
3. Действие указывает что делать с переменными в конце заданной локиги цыкла
Ну и в конце goto для того что бы прыгнуть на аддрес байкода метода в начало условия или в конец в зависимости от результата компараторов

На примере
C++:
Expand Collapse Copy
for (int i = 0; i < 5; i++) {

    System.out.println(i);

}

Тоже самое что и
C++:
Expand Collapse Copy
int i = 0;
while (i < 5) {
    System.out.println(i);
    i++;
}

Для JVM все равно что ты будешь использовать, это дело вкуса и стиля.
Восле компилиции javac FOR упомянотый выше вылгядит так

C++:
Expand Collapse Copy
0: iconst_0
1: istore_1          // Инициализация переменной i = 0

2: iload_1
3: iconst_5
4: if_icmpge 16      // Для выхода из цакла если значение сопоставимо с условием прыгнув дальше по адресу возврата

// #2 #3 Выдуманые id указывающие на константы в Constant Pool метода
7:  getstatic     #2      // java/lang/System.out:Ljava/io/PrintStream;
10: iload_1
11: invokevirtual #3      // Method java/io/PrintStream.println:(I)V

14: iinc 1, 1        // Просто увеличивает значение в локальной переменной по аддресу 1 на 1 за действие
15: goto 2           // Назад к условию прыкнув на инструкцию 2 загрузив

iconst_0 - Ложит в на вершину operand stack 0
istore_1 - Выталкивает iconst_0 и ложит в local variable array
iload_1 - Копирует зачение 0 из local variable array ложа обратно на вершину operand stack
iconst_5 - Ложит 5 в local variable array
if_icmpge 16 - Вытаскивает верхние положыные числа 0 и 5 и сравнивает, если числа одинаковые то прыгает на аддрес 16
getstatic System.out - Получает объект вывода и ложит ссылку на него на вершину operand stack
iload_1 - Копирует текущее значение переменной из local variable array в operand stack
invokevirtual println - Выталкивает из operand stack ссылку на объект и значение, выполняет вывод и очищает стек
iinc 1, 1 - Берет значение в local variable array по адресу 1 и прямо там прибавляет к нему 1
goto 2 - Переносит выполнение обратно на адрес 2 для новой проверки условия

После интерпретации идет JIT (c1/c2) который уже перестает исполнять байткод напрямую
JIT строит граф управления потоком и переводит код во внутреннее представление (IR/SSA)

Operand stack и local variable array больше не используются
Переменные становятся виртуальными регистрами

Переменная i анализируется - инициализируется константой, изменяется тольк в одном месте, не утекает за пределы метода JIT понимает, что i это счетчик цикла i переносится в регистр CPU инструкции iload_1, istore_1 и iinc удаляются
проверка условия if_icmpge превращается в сравнение регистра с константой и условный jump процессора goto превращается в обычный jump процессора

После JIT JVM больше не исполняет байткод, выполняется нативный машинный код
 
Ну смотри оператор FOR это синтаксическая композиция для улучшения читаемости кода
Сам по себе является обычный цыклои WHILE но имеет иную структуру (инициализация; условие; действие)
На уровне JVM он не существует как конструкция, а при компиляции декомпозируется в набор независимых фрагментов управления потоком, связанных условными и безусловными переходами байткода.

1. Инициализация создает обычные локальные переменные в Local Variable Table
2. Условие это обычные компараторы по типу if_icmpge, if_icmpne, if_icmplt, if_icmpgt, if_icmple, if_icmpge все они нешают нужно ли повторять логику или нет
3. Действие указывает что делать с переменными в конце заданной локиги цыкла
Ну и в конце goto для того что бы прыгнуть на аддрес байкода метода в начало условия или в конец в зависимости от результата компараторов

На примере
C++:
Expand Collapse Copy
for (int i = 0; i < 5; i++) {

    System.out.println(i);

}

Тоже самое что и
C++:
Expand Collapse Copy
int i = 0;
while (i < 5) {
    System.out.println(i);
    i++;
}

Для JVM все равно что ты будешь использовать, это дело вкуса и стиля.
Восле компилиции javac FOR упомянотый выше вылгядит так

C++:
Expand Collapse Copy
0: iconst_0
1: istore_1          // Инициализация переменной i = 0

2: iload_1
3: iconst_5
4: if_icmpge 16      // Для выхода из цакла если значение сопоставимо с условием прыгнув дальше по адресу возврата

// #2 #3 Выдуманые id указывающие на константы в Constant Pool метода
7:  getstatic     #2      // java/lang/System.out:Ljava/io/PrintStream;
10: iload_1
11: invokevirtual #3      // Method java/io/PrintStream.println:(I)V

14: iinc 1, 1        // Просто увеличивает значение в локальной переменной по аддресу 1 на 1 за действие
15: goto 2           // Назад к условию прыкнув на инструкцию 2 загрузив

iconst_0 - Ложит в на вершину operand stack 0
istore_1 - Выталкивает iconst_0 и ложит в local variable array
iload_1 - Копирует зачение 0 из local variable array ложа обратно на вершину operand stack
iconst_5 - Ложит 5 в local variable array
if_icmpge 16 - Вытаскивает верхние положыные числа 0 и 5 и сравнивает, если числа одинаковые то прыгает на аддрес 16
getstatic System.out - Получает объект вывода и ложит ссылку на него на вершину operand stack
iload_1 - Копирует текущее значение переменной из local variable array в operand stack
invokevirtual println - Выталкивает из operand stack ссылку на объект и значение, выполняет вывод и очищает стек
iinc 1, 1 - Берет значение в local variable array по адресу 1 и прямо там прибавляет к нему 1
goto 2 - Переносит выполнение обратно на адрес 2 для новой проверки условия

После интерпретации идет JIT (c1/c2) который уже перестает исполнять байткод напрямую
JIT строит граф управления потоком и переводит код во внутреннее представление (IR/SSA)

Operand stack и local variable array больше не используются
Переменные становятся виртуальными регистрами

Переменная i анализируется - инициализируется константой, изменяется тольк в одном месте, не утекает за пределы метода JIT понимает, что i это счетчик цикла i переносится в регистр CPU инструкции iload_1, istore_1 и iinc удаляются
проверка условия if_icmpge превращается в сравнение регистра с константой и условный jump процессора goto превращается в обычный jump процессора

После JIT JVM больше не исполняет байткод, выполняется нативный машинный код
Тоесть использовать for и while разницы нет? Или есть какие-то случаи когда можно использовать только какойто 1?
 
Тоесть использовать for и while разницы нет? Или есть какие-то случаи когда можно использовать только какойто 1?
смотри сам я java не знаю(допустим нам надо перебрать массив чтобы найти в нем какое либо число то тут скорее всего лутьше использовать for чем while мы знаем сколько в массиве элементов for(int i = 0;i<=размер массива допустим 5;i++)и перебираем массив мы знаем сколько придет чисел мы точно указываем сколько будет работать цикл 5 раз в while() представим задачу нам водит пользователь числа и у нас должна работать программа до тех пор пока пользователь не введет число мы не знаем сколько введет нам пользователь легче использовать while(true){получаем числа и сравнимаем через if(допустим переменная a == 0 break;}
смотри сам я java не знаю(допустим нам надо перебрать массив чтобы найти в нем какое либо число то тут скорее всего лутьше использовать for чем while мы знаем сколько в массиве элементов for(int i = 0;i<=размер массива допустим 5;i++)и перебираем массив мы знаем сколько придет чисел мы точно указываем сколько будет работать цикл 5 раз в while() представим задачу нам водит пользователь числа и у нас должна работать программа до тех пор пока пользователь не введет число мы не знаем сколько введет нам пользователь легче использовать while(true){получаем числа и сравнимаем через if(допустим переменная a == 0 break;}
(в падлу ставить запятые всю ночь не спал по этому да )
 
Последнее редактирование:
Тоесть использовать for и while разницы нет? Или есть какие-то случаи когда можно использовать только какойто 1?
For используй если работаешь с коллекциями или известно условие продолжения например до 5, а while когда ты вообще не знаешь сколько раз сработает код, он бесконечный или у тебя есть boolean перемеая которая задает активен код или нет. Еще может быть много вариантов надо смотреть по ситуации
 
Последнее редактирование:
Назад
Сверху Снизу