Какая альтернативная функция для ключевого слова goto в Java?
Поскольку в Java нет goto.
Какая альтернативная функция для ключевого слова goto в Java?
Поскольку в Java нет goto.
Ответы:
Вы можете использовать пометку BREAK :
search:
for (i = 0; i < arrayOfInts.length; i++) {
for (j = 0; j < arrayOfInts[i].length; j++) {
if (arrayOfInts[i][j] == searchfor) {
foundIt = true;
break search;
}
}
}
Однако в правильно спроектированном коде функциональность GOTO не требуется.
Нет прямого эквивалента goto
Java концепции. Есть несколько конструкций, которые позволяют вам делать то же, что и с классикой goto
.
break
и continue
позволяют выйти из блока в цикле или операторе переключения.break <label>
позволяющий перейти из произвольного составного оператора на любой уровень в рамках данного метода (или блока инициализатора).continue <label>
продолжить следующую итерацию внешнего цикла из внутреннего цикла.return
.Ни одна из этих конструкций Java не позволяет выполнить переход назад или к точке кода на том же уровне вложенности, что и текущий оператор. Все они выпрыгивают из одного или нескольких уровней вложенности (области действия), и все (кроме continue
) прыгают вниз. Это ограничение помогает избежать синдрома «спагетти-кода» goto, присущего старым кодам BASIC, FORTRAN и COBOL 2 .
1- Самая дорогая часть исключений - это фактическое создание объекта исключения и его трассировки стека. Если вам действительно действительно нужно использовать обработку исключений для «нормального» управления потоком, вы можете либо предварительно выделить / повторно использовать объект исключения, либо создать собственный класс исключения, который переопределяет fillInStackTrace()
метод. Обратной стороной является то, что исключениеprintStackTrace()
методы не дадут вам полезной информации ... если вам когда-нибудь понадобится их вызвать.
2. Синдром спагетти-кода породил подход структурированного программирования , при котором вы ограничиваете использование доступных языковых конструкций. Это можно было применить к BASIC , Fortran и COBOL , но это требовало осторожности и дисциплины. Полное избавление от этого goto
было прагматически лучшим решением. Если вы сохраните это на языке, всегда найдется какой-нибудь клоун, который будет злоупотреблять этим.
Ради удовольствия, вот реализация GOTO на Java.
Пример:
1 public class GotoDemo { 2 public static void main(String[] args) { 3 int i = 3; 4 System.out.println(i); 5 i = i - 1; 6 if (i >= 0) { 7 GotoFactory.getSharedInstance().getGoto().go(4); 8 } 9 10 try { 11 System.out.print("Hell"); 12 if (Math.random() > 0) throw new Exception(); 13 System.out.println("World!"); 14 } catch (Exception e) { 15 System.out.print("o "); 16 GotoFactory.getSharedInstance().getGoto().go(13); 17 } 18 } 19 }
Запускаем это:
$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo 3 2 1 0 Hello World!
Нужно ли мне добавлять «не использовать!»?
Math.random()
может возвращать 0. Должно быть> =
HellWorld!o World!
выходом и придет в замешательство. #AllBugsAreFeatures
Хотя некоторые комментаторы и отрицательные голоса утверждают, что это не goto , сгенерированный байт-код из приведенных ниже операторов Java действительно предполагает, что эти операторы действительно выражают семантику goto .
В частности, do {...} while(true);
цикл во втором примере оптимизирован компиляторами Java, чтобы не оценивать условие цикла.
label: {
// do stuff
if (check) break label;
// do more stuff
}
В байт-коде:
2 iload_1 [check]
3 ifeq 6 // Jumping forward
6 ..
label: do {
// do stuff
if (check) continue label;
// do more stuff
break label;
} while(true);
В байт-коде:
2 iload_1 [check]
3 ifeq 9
6 goto 2 // Jumping backward
9 ..
continue label
прыжок назад
// do stuff
и // do more stuff
являются интересующими утверждениями, continue label
"имеет эффект" прыжка назад ( while(true)
конечно, из-за утверждения). Я не знал, что это был такой точный вопрос ...
while(true)
компилятором в goto
операцию байт-кода. Как true
постоянный литерал, компилятор может выполнять эту оптимизацию и не должен ничего оценивать. Итак, мой пример действительно - это goto, прыжок назад ...
Если вы действительно хотите что-то вроде операторов goto, вы всегда можете попробовать разбить на именованные блоки.
Вы должны находиться в рамках блока, чтобы перейти к метке:
namedBlock: {
if (j==2) {
// this will take you to the label above
break namedBlock;
}
}
Я не буду читать вам лекцию о том, почему вам следует избегать goto - я предполагаю, что вы уже знаете ответ на этот вопрос.
public class TestLabel {
enum Label{LABEL1, LABEL2, LABEL3, LABEL4}
/**
* @param args
*/
public static void main(String[] args) {
Label label = Label.LABEL1;
while(true) {
switch(label){
case LABEL1:
print(label);
case LABEL2:
print(label);
label = Label.LABEL4;
continue;
case LABEL3:
print(label);
label = Label.LABEL1;
break;
case LABEL4:
print(label);
label = Label.LABEL3;
continue;
}
break;
}
}
public final static void print(Label label){
System.out.println(label);
}
StephenC пишет:
Есть две конструкции, которые позволяют вам делать некоторые из вещей, которые вы можете делать с классическим goto.
Еще один...
Мэтт Вулф пишет:
Люди всегда говорят о том, чтобы никогда не использовать goto, но я думаю, что есть действительно хороший пример использования в реальном мире, который довольно хорошо известен и используется ... То есть, убедитесь, что вы выполнили некоторый код перед возвратом из функции ... Обычно его освобождение замки или что-то еще, но в моем случае я бы хотел иметь возможность прыгнуть на перерыв прямо перед возвратом, чтобы я мог выполнить требуемую обязательную очистку.
try {
// do stuff
return result; // or break, etc.
}
finally {
// clean up before actually returning, even though the order looks wrong.
}
http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
Блок finally всегда выполняется при выходе из блока try. Это гарантирует выполнение блока finally даже в случае возникновения непредвиденного исключения. Но наконец, он полезен не только для обработки исключений - он позволяет программисту избежать случайного обхода кода очистки посредством возврата, продолжения или прерывания. Помещение кода очистки в блок finally всегда является хорошей практикой, даже если не ожидается никаких исключений.
Глупый вопрос на собеседовании, связанный с finally, звучит так: если вы вернетесь из блока try {}, но также получите результат в своем finally {}, какое значение будет возвращено?
return
в finally
блок - плохая идея. (И даже если знание не является строго необходимым, я бы побеспокоился о программисте, у которого не было бы любопытства узнать ...)
Самый простой:
int label = 0;
loop:while(true) {
switch(state) {
case 0:
// Some code
state = 5;
break;
case 2:
// Some code
state = 4;
break;
...
default:
break loop;
}
}
Попробуйте приведенный ниже код. Меня устраивает.
for (int iTaksa = 1; iTaksa <=8; iTaksa++) { // 'Count 8 Loop is 8 Taksa
strTaksaStringStar[iCountTaksa] = strTaksaStringCount[iTaksa];
LabelEndTaksa_Exit : {
if (iCountTaksa == 1) { //If count is 6 then next it's 2
iCountTaksa = 2;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 2) { //If count is 2 then next it's 3
iCountTaksa = 3;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 3) { //If count is 3 then next it's 4
iCountTaksa = 4;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 4) { //If count is 4 then next it's 7
iCountTaksa = 7;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 7) { //If count is 7 then next it's 5
iCountTaksa = 5;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 5) { //If count is 5 then next it's 8
iCountTaksa = 8;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 8) { //If count is 8 then next it's 6
iCountTaksa = 6;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 6) { //If count is 6 then loop 1 as 1 2 3 4 7 5 8 6 --> 1
iCountTaksa = 1;
break LabelEndTaksa_Exit;
}
} //LabelEndTaksa_Exit : {
} // "for (int iTaksa = 1; iTaksa <=8; iTaksa++) {"
В Java этого нет goto
, потому что он делает код неструктурированным и нечетким для чтения. Однако вы можете использовать break
и continue
как цивилизованную форму goto без проблем.
ahead: {
System.out.println("Before break");
break ahead;
System.out.println("After Break"); // This won't execute
}
// After a line break ahead, the code flow starts from here, after the ahead block
System.out.println("After ahead");
Выход :
Before Break
After ahead
before: {
System.out.println("Continue");
continue before;
}
Это приведет к бесконечной петле , как каждый раз , когда линия continue before
выполнена, поток кода будет снова начать сbefore
.
goto
он доступен на Java? Я думаю, что в этом заключается более важный вопрос.