Java Продолжить Метка устарела? - PullRequest
16 голосов
/ 11 июля 2011

У меня есть 2 форса, после вложенного для меня есть некоторый код, который я не хочу выполнять, если условие истинно внутри вложенного для. Если я использую break, этот код будет выполняться, поэтому (как я узнал в SCJP) я использовал continue label; для внешнего for. Это устаревшее использование Java? Старомодно? Кто-то предлагал использовать рекурсию или что-то еще, но для меня это совершенно нормально, просто, актуально и идеально подходит для этого.

here:
for (bla bla) {
   for (bla bla) {
      if (whatever) continue here;
   }
// some code I don't want to execute if whatever is true
}

Спасибо

Отредактировано:
Если я перефразирую свой вопрос следующим образом: Как вы можете «перемещаться» между несколькими вложенными форами? Этот подход будет «рекомендуемым» способом? потому что это то, что говорится в Книге SCJP. Если нет .. будет ли это означать, что Katherine Sierra и Bert Bates неверны?

Отредактировано2:
Почему continue label; не рекомендуется? Я хочу получить ответ на концепции или внутри ООП или Java, что может пойти не так ..

Ответы [ 6 ]

7 голосов
/ 11 июля 2011

Я бы сделал рефакторинг, чтобы сделать его более читабельным.

Пример:

if (!checkWhatever()) {
    // some code I don't want to execute if whatever is true
}
boolean checkWhatever() {
    for (bla bla) {
       for (bla bla) {
          if (whatever) return false;
       }
    }
    return true;
}
5 голосов
/ 11 июля 2011

Ответ: это зависит. Если вы часто используете continue, это может быть признаком того, что ваш код нуждается в рефакторинге. Тем не менее, в сценарии, который вы дали, похоже, что все в порядке, чтобы использовать его.

3 голосов
/ 11 июля 2011

Я бы сказал, что его обескураживают. Он по-прежнему имеет действительное использование, где альтернативы являются более сложными или подвержены ошибкам (то есть не улучшаются)

2 голосов
/ 20 апреля 2012

Со ссылкой на ваш Edit 2, он всегда будет выглядеть немного сомнительно, потому что он нарушает более раннюю ортодоксальность программирования, чем OO: «структурированное программирование» (см. http://en.wikipedia.org/wiki/Structured_programming). Это также похоже на goto, и все хорошие программисты знают, что им нужно идти на исповедь, если они позволяют goto войти в свой код.

Может возникнуть некоторая обеспокоенность тем, что компилятору будет сложнее анализировать поток управления функцией, но этот инструмент обычно используется для повышения эффективности. Например, реализация Apache java.lang.String использует ее в этой функции, которая по крайней мере предназначена для оптимизации:

/*
 * An implementation of a String.indexOf that is supposed to perform
 * substantially better than the default algorithm if the "needle" (the
 * subString being searched for) is a constant string.
 *
 * For example, a JIT, upon encountering a call to String.indexOf(String),
 * where the needle is a constant string, may compute the values cache, md2
 * and lastChar, and change the call to the following method.
 */
@SuppressWarnings("unused")
private static int indexOf(String haystackString, String needleString,
        int cache, int md2, char lastChar) {
    char[] haystack = haystackString.value;
    int haystackOffset = haystackString.offset;
    int haystackLength = haystackString.count;
    char[] needle = needleString.value;
    int needleOffset = needleString.offset;
    int needleLength = needleString.count;
    int needleLengthMinus1 = needleLength - 1;
    int haystackEnd = haystackOffset + haystackLength;
    outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
        if (lastChar == haystack[i]) {
            for (int j = 0; j < needleLengthMinus1; ++j) {
                if (needle[j + needleOffset] != haystack[i + j
                        - needleLengthMinus1]) {
                    int skip = 1;
                    if ((cache & (1 << haystack[i])) == 0) {
                        skip += j;
                    }
                    i += Math.max(md2, skip);
                    continue outer_loop;
                }
            }
            return i - needleLengthMinus1 - haystackOffset;
        }

        if ((cache & (1 << haystack[i])) == 0) {
            i += needleLengthMinus1;
        }
        i++;
    }
    return -1;
}
1 голос
/ 28 ноября 2013

Рефакторинг, чтобы сделать его более читабельным, поместив внутренний цикл в свой собственный метод:

for (bla bla) {   
  DoStuff();
}
void DoStuff() {
  for (bla bla) {
    if (whatever) return;
  }
  // some code to execute when whatever is false.
}

Принцип: Если метод становится достаточно сложным, чтобы требовать МАРКИРОВКУ блока, рассмотрите возможность рефакторинга части этого методав отдельный метод, такой, что метка не нужна.

Точно так же неразумно делать методы с тремя циклами.Если только петли не очень простые.Даже если ярлыки не нужны.Убедитесь, что самая внешняя конструкция потока (цикл, или if / else, или переключатель) легко читается, скрывая сложность внутри других методов.Даже если эти методы вызываются только из одного места.

0 голосов
/ 17 июля 2014

Используйте логическое значение, называемое «успех» или что-то в этом роде. Намного легче читать и следовать за потоком. Gotos следует использовать только для обработки ошибок.

boolean success = true;
for(int outer = 0; (outer <= outerLimit) && sucess; outer++)
{
    for(int inner = 0; (inner <= innerLimit) && success; inner++)
    {
        if( !doInnerStuff() )
        {
            success = false;
        }
    }

    if( success )
    {
        success = doOuterStuff();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...