Должен ли я избегать использования выражений Java Label? - PullRequest
67 голосов
/ 05 сентября 2008

Сегодня у меня был коллега, предложивший мне реорганизовать мой код для использования оператора label для управления потоком через 2 вложенных цикла for, которые я создал. Я никогда не использовал их раньше, потому что лично я думаю, что они снижают читаемость программы. Я готов изменить свое мнение об их использовании, если аргумент достаточно тверд, как бы то ни было. Что думают люди о заявлениях на этикетках?

Ответы [ 11 ]

49 голосов
/ 05 сентября 2008

Многие алгоритмы выражаются легче, если вы можете перепрыгнуть через два цикла (или цикл, содержащий оператор switch). Не переживай из-за этого. С другой стороны, это может указывать на слишком сложное решение. Так что отойдите и посмотрите на проблему.

Некоторые люди предпочитают подход «один вход, один выход» для всех циклов. То есть избегать разрыва (и продолжения) и досрочного возврата для циклов в целом. Это может привести к дублированию кода.

Чего я бы настоятельно не хотел делать, так это вводить вспомогательные переменные. Сокрытие потока управления внутри состояния добавляет путаницы.

Разделение помеченных петель на два метода может оказаться затруднительным. Исключения, вероятно, слишком тяжелые. Попробуйте подход с одним входом и одним выходом.

33 голосов
/ 05 сентября 2008

Метки похожи на goto: используйте их экономно, и только тогда, когда они делают ваш код быстрее и , что более важно, более понятно,

Например, если вы находитесь в больших циклах глубиной в шесть уровней и сталкиваетесь с условием, которое делает бессмысленным выполнение остальной части цикла, нет смысла иметь 6 дополнительных люков в ваших операторах условий для раннего выхода из цикла.

Этикетки (и гото) не являются злыми, просто люди иногда используют их не по назначению. Большую часть времени мы на самом деле пытаемся написать наш код, чтобы он был понятен вам и следующему программисту. Сделать его сверхбыстрым - это вторичная проблема (опасайтесь преждевременной оптимизации).

При неправильном использовании Labels (и goto's) код становится менее читабельным, что вызывает огорчение у вас и у следующего разработчика. Компилятору все равно.

27 голосов
/ 27 января 2009

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

Кстати: это компилируется и запускается.

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}
8 голосов
/ 05 сентября 2008

Мне любопытно услышать, какова ваша альтернатива лейблам. Я думаю, что это в значительной степени сводится к аргументу «вернуть как можно раньше» против «используйте переменную для хранения возвращаемого значения и возврата только в конце».

Метки довольно стандартны, когда у вас есть вложенные циклы. Единственный способ, которым они действительно снижают читабельность, - это когда другой разработчик никогда не видел их раньше и не понимает, что они означают.

5 голосов
/ 20 апреля 2010

Я использовал цикл с меткой Java для реализации метода Sieve для поиска простых чисел (сделано для одной из математических задач проекта Эйлера), что сделало его в 10 раз быстрее по сравнению с вложенными циклами. Например, если (определенное условие) вернуться к внешнему циклу.

private static void testByFactoring() {
    primes: for (int ctr = 0; ctr < m_toFactor.length; ctr++) {
        int toTest = m_toFactor[ctr];
        for (int ctr2 = 0; ctr2 < m_divisors.length; ctr2++) {
            // max (int) Math.sqrt(m_numberToTest) + 1 iterations
            if (toTest != m_divisors[ctr2]
                        && toTest % m_divisors[ctr2] == 0) {
                continue primes; 
            }
        } // end of the divisor loop
    } // end of primes loop
} // method

Я спросил программиста на C ++, как плохо помечены циклы, он сказал, что будет использовать их экономно, но иногда они могут пригодиться. Например, если у вас есть 3 вложенных цикла и для определенных условий вы хотите вернуться к самому внешнему циклу.

Таким образом, у них есть свои цели, это зависит от проблемы, которую вы пытались решить.

5 голосов
/ 26 января 2009

Я бы поспорил в их пользу в некоторых местах, я нашел их особенно полезными в этом примере:


nextItem: for(CartItem item : user.getCart()) {

  nextCondition : for(PurchaseCondition cond : item.getConditions()) {
     if(!cond.check())
        continue nextItem;
     else
        continue nextCondition;

  }
  purchasedItems.add(item);
}
5 голосов
/ 25 сентября 2008

Я думаю, что с новым циклом for-each метка может быть действительно четкой.

Например:

sentence: for(Sentence sentence: paragraph) {
  for(String word: sentence) {
    // do something
    if(isDone()) {
      continue sentence;
    }
  }
}

Я думаю, что это выглядит действительно ясно, если ваш ярлык совпадает с вашей переменной в новом for-each. На самом деле, может быть, Java должна быть злой и добавлять неявные метки для каждой переменной хех

5 голосов
/ 06 сентября 2008

Я никогда не видел меток, используемых "в дикой природе" в коде Java. Если вы действительно хотите разбить вложенные циклы, посмотрите, сможете ли вы реорганизовать ваш метод так, чтобы ранний оператор return делал то, что вы хотите.

Технически, я думаю, между ранним возвратом и лейблом не так много различий. Практически, однако, почти каждый разработчик Java видел раннее возвращение и знает, что он делает. Я предполагаю, что многие разработчики, по крайней мере, будут удивлены лейблом и, вероятно, будут сбиты с толку.

Меня учили ортодоксальности однократного входа / однократного выхода, но с тех пор я стал ценить ранние операторы возврата и разрывание циклов как способ упростить код и сделать его более понятным.

3 голосов
/ 05 сентября 2008

Я никогда не использую метки в своем коде. Я предпочитаю создать охрану и инициализировать его null или другим необычным значением. Этот охранник часто является объектом результата. Я не видел ни одного из моих коллег, использующих ярлыки, и не нашел ни одного в нашем хранилище. Это действительно зависит от вашего стиля кодирования. По моему мнению, использование меток уменьшит читабельность, так как это не распространенная конструкция и обычно она не используется в Java.

1 голос
/ 10 апреля 2016

Да, вы должны избегать использования меток, если нет особой причины их использовать (уместно привести пример упрощения реализации алгоритма). В таком случае я бы посоветовал добавить достаточное количество комментариев или другой документации, чтобы объяснить причины этого, чтобы кто-то не пришел позже и не исказил это из-за некоторого понятия «улучшения кода» или «избавления от запаха кода» или какое-то другое, потенциально BS оправдание.

Я бы приравнял этот тип вопроса к решению, когда следует или не следует использовать троицу, если. Основное обоснование заключается в том, что это может ухудшить читабельность, и если программист не будет очень осторожно называть вещи разумным образом, использование соглашений, таких как метки, может ухудшить ситуацию. Предположим, что в примере, использующем «nextCondition» и «nextItem», использовались «loop1» и «loop2» для имен его меток.

Личные ярлыки - это одна из тех функций, которые не имеют большого смысла для меня, кроме Assembly или BASIC и других аналогично ограниченных языков. У Java есть много более обычных / регулярных циклов и управляющих конструкций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...