Как Java знает, куда прыгать при выходе из цикла?
while (condition) {
if (condition) {
statement1;
statement2;
break;
} else {
statement3;
statement4;
}
}
Используя break
в предложении if, мы гарантируем, что цикл остановлен и вышел.
Я не понимаю, как оператор break "знает", что он находится в цикле для его выхода изначально или как он "знает", куда перейти. Как это происходит?
Ответы
Ответ 1
Я не понимаю, как оператор break "знает", что он находится в цикле для его выхода изначально.
Оператор break
не знает, что он находится в операторе switch
или цикла. Компилятор проверяет, что оператор break
находится в операторе switch
или цикла. Если он встречает оператор break
, который не входит в оператор цикла, он выдаст ошибку времени компиляции.
Если инструкция switch
, while
, do
или for
в непосредственном вложении метода, конструктор или инициализатор содержит оператор break, возникает ошибка времени компиляции.
Если компилятор может проверить, что оператор break
находится в операторе switch
или цикла, он затем выдаст инструкции JVM для внезапного перехода в первый оператор сразу после ближайшего замкнутого цикла.
Таким образом:
for(int i = 0; i < 10; i++) {
if(i % 2 == 0) {
break;
}
}
будет переведен компилятором в:
0: iconst_0 # push integer 0 onto stack
1: istore_1 # store top of stack in local 1 as integer
# i = 0
2: iload_1 # push integer in local 1 onto stack
3: bipush 10 # push integer 10 onto stack
5: if_icmpge 23 # pop and compare top two (as integers), jump if first >= second
# if i >= 10, end for
8: iload_1 # push integer in local 1 onto stack
9: iconst_2 # push integer 2 onto stack
10: irem # pop top two and computes first % second and pushes result
# i % 2
11: ifne 17 # pop top (as integer) and jump if not zero to 17
# if(i % 2 == 0)
14: goto 23 # this is the break statement
17: iinc 1, 1 # increment local 1 by 1
# i++
20: goto 2 # go to top of loop
# loop
23: return # end of loop body
Ответ 2
break
не является вашей стандартной функцией. Это ключевое слово, используемое компилятором Java. Когда он увидит это, он будет вставлять инструкцию байт-кода для перехода непосредственно за пределы цикла после него. Это простой байт-код goto, как показано в ответе Джейсона.
Аналогично, ключевое слово continue
эффективно перескакивает в начало цикла 1.
return
делает это из функционального блока, хотя и имеет несколько отличий, поскольку может потребоваться перенос значения или ссылки, указывающей на кучу.
1 - На самом деле это немного сложнее, чем это. Вероятно, лучшая простая, но точная "модель", которая работает для всех циклов Java, заключается в том, что continue
эквивалентно прыжку в воображаемую пустую инструкцию в конце тела цикла.
Ответ 3
Я не понимаю, как оператор break "знает", что он находится в цикле для его выхода изначально.
Компилятор превращает вашу программу в дерево разбора. Все в дереве разбора имеет родительский элемент, кроме корня. Оператор break должен иметь родительский цикл где-то вверх по дереву (или, конечно же, родительский оператор switch).
Ответ 4
Если вы когда-либо взглянули на сборку или байт-код Java, это будет иметь больше смысла. На более низком уровне ваша программа скомпилирована в "байт-код", который использует регистры, адреса и т.д. Простой оператор if может быть переведен на следующее:
3: if_icmpeq 5
4: goto 10
5: iconst_1
6: iload_1
7: iconst_2
8: iload_2
9: if_icmpeq 10
10: // end of if-else statement
Это может быть (очень плохо) байт-код для:
if ( x == y )
if ( 1 == 2 )
По сути, на более низком уровне вы используете метки/номера строк и gotos для перехода по коду. Таким образом, break
по существу означает, goto последняя строка оператора if или цикла.
Ответ 5
Оператор break имеет две формы: с меткой и без метки.
Вы можете использовать немеченный разрыв для завершения for, while, or do-while loop.
Оператор без метки завершает innermost switch, for, while, or do-while statement
, но labeled break terminates an outer statement
.
search:
for (i = 0; i < arrayOfInts.length; i++) {
for (j = 0; j < arrayOfInts[i].length;
j++) {
if (arrayOfInts[i][j] == 5) {
foundIt = true;
break search;
}
}
}
Надеюсь, это поможет.