Команда goto реализует безусловный переход на уровне исходного текста программы, и именно это обстоятельство принесло ей дурную славу. Если программа постоянно «прыгает» из одного места в другое, нет ли способа реорганизовать ее код так, чтобы управление программой перестало быть таким «прыгучим»? Команда goto впала в настоящую немилость с опубликованием знаменитой статьи Эдгара Дейкстры «Команда GOTO вредна» (Goto considered harmful), их тех пор порицание команды goto стало чуть ли не спортом, а защитники репутации многострадального оператора разбежались по укромным углам.
Как всегда в ситуациях такого рода, существует «золотая середина». Проблема состоит не в использовании goto вообще, но в злоупотреблении — все же иногда именно оператор goto позволяет лучше всего организовать управление программой.
>1 Оригинал статьи Go То Statement considered harmful имеет постоянный адрес в Интернете: http:// www.acm.org/classics/oct95. — Примеч. ред.
Хотя слово goto зарезервировано в языке Java, оно там не используется; Java не имеет команды goto. Однако существует механизм, чем-то похожий на безусловный переход и осуществляемый командами break и continue. Скорее, это способ прервать итерацию цикла, а не передать управление в другую точку программы. Причина его обсуждения вместе с goto состоит в том, что он использует тот же механизм — метки.
Метка представляет собой идентификатор с последующим двоеточием:
label 1•
Единственное место, где в Java метка может оказаться полезной, — прямо перед телом цикла. Причем никаких дополнительных команд между меткой и телом цикла быть не должно. Причина помещения метки перед телом цикла может быть лишь одна — вложение внутри цикла другого цикла или конструкции выбора. Обычные версии break и continue прерывают только текущий цикл, в то время как их версии с метками способны досрочно завершать циклы и передавать выполнение в точку, адресуемую меткой:
labell:
внешний-цикл {
внутренний-цикл { //.
break; // 1 // .
continue; // 2 //..
continue labell; // 3 //...
break labell; // 4
В первом случае (1) команда break прерывает выполнение внутреннего цикла, и управление переходит к внешнему циклу. Во втором случае (2) оператор continue передает управление к началу внутреннего цикла. Но в третьем варианте (3) команда continue labell влечет выход из внутреннего и внешнего циклов и возврат к метке labell. Далее выполнение цикла фактически продолжается, но с внешнего цикла. В четвертом случае (4) команда break labell также вызывает переход к метке labell, но на этот раз повторный вход в итерацию не происходит. Это действие останавливает выполнение обоих циклов. Пример использования цикла for с метками:
//: control/LabeledFor.java
// Цикл for с метками
import static net.mindview.util.Print.*;
public class LabeledFor {
public static void main(String[] args) { int i = 0;
outer- // Другие команды недопустимы for(; true ,) { // infinite loop
inner: // Другие команды недопустимы for(; i < 10; i++) {
printC'i = " + i);
if(i == 2) {
print("continue"); continue;
}
if(i == 3) {