Урок 12. Оператор switch в Java


На этом уроке из курса Java мы поговорим об операторе Java switch.

Оператор switch

Оператор switch - это другой тип условного выражения. Он похож на if, но в некоторых случаях оно может быть более кратким. Вам пока не нужно думать о точном значении, как мы дойдем до него в примере ниже.

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

public enum LoggingLevel {
    PENDING, PROCESSING, PROCESSED;
}
Оператор switch:

LoggingLevel state = LoggingLevel.PENDING;

switch (state) {
   case PENDING:
      onPending();
      break;
   case PROCESSING:
      onProcessing();
      break;
   case PROCESSED:
      onProcessed();
      break;
}
Синтаксически, это похоже на выражение if. Внутри оператора мы записываем переменную, которую пытаемся сравнить, в данном случае состояние. Каждый случай - это потенциальное значение переключателя, с которым мы пытаемся сравнить. То есть, дело в ожидании: примерно то же самое, что сказать: если (status == Status.PENDING). Внутренняя сторона каждого случая аналогична внутренней стороне фигурных скобок оператора if. Чтобы завершить обращение, можно ввести слово break или написать инструкцию return. Если у вас нет ни того, ни другого, код "проваливается", идея, которую я объясню в следующем разделе.

Если у вас есть только одно значение, то оператор if более лаконичен, так как операторы switch имеют дополнительные накладные расходы на запись switch (status) {...}. Однако оператор switch предпочтительнее, когда вы перебираете несколько значений с короткими блоками кода, такими как вызов метода, внутри каждого условия. Чем больше у вас условий, тем короче оператор switch по сравнению с эквивалентными ветвями операторов if.

Другой альтернативой, чтобы избежать провала, является возврат значения внутри оператора switch, чтобы оставить окружающий метод:

private String process(LoggingLevel state) {
    switch (state) {
         case PENDING:
              return pendingAsString();
         case PROCESSING:
              return processingAsString();
         case PROCESSED:
              return processedAsString();
    }
    return defaultString();
}
Это завершает метод и, следовательно, не попадает в остальную часть инструкции switch. В этом случае возвращаемое значение нашего метода process - String. Если ни один случай не выполняется, мы вернем строку по умолчанию.

Провал

Теперь посмотрите код:

switch (state) {
    case PENDING:
         onPending();
         break;
    case PROCESSING:
         onProcessing();
    case PROCESSED:
         onProcessed();
         break;
}
Он является примером оператора switch, в котором отсутствует оператор break для обработки обращения. Учитывая состояние ожидания, мы бы вызвали логику ожидания, оставив переключатель полностью с инструкцией break. Это работает так, как задумано.

Однако, учитывая статус обработки, мы в конечном итоге вызова как onProcessing()и onProcessed() метод. Другими словами, ПРОЦЕССИНГОВОЕ обращение переходит в обработанное обращение. В этом примере оба случая имеют свой собственный независимый код внутри, так что, вероятно, он не должен был провалиться.

Это может быть полезно, если вы хотите, чтобы два случая выполняли один и тот же код. Поскольку в операторе switch нет возможности сказать “и", чтобы избежать дублирования кода, Вы можете провалиться в первом случае, а затем написать код во втором.

Инструкции Switch, которые проваливаются, являются большим источником ошибок и очень опасны, поскольку отсутствие инструкций break может быть трудно обнаружить. Если вы действительно хотите, чтобы ваш оператор switch провалился, оставьте комментарий, говорящий так, как если бы он сказал следующему программисту: “этот коммутатор проваливается намеренно.- ...Иначе у него может возникнуть искушение “починить” его.

По умолчанию (default)

Синтаксис операторов switch не требует обращения ко всем возможным значениям. Вы можете оставить дела без внимания. Когда нет подходящих делу, наш оператор switch завершается, ничего не делая. Альтернативой тому, чтобы ничего не делать, когда никакие случаи не совпадают, является добавление предложения по умолчанию, как я сделал в примере ниже, которое совпадает, когда ни один из других случаев не применяется.

switch (state) {
    case PENDING:
         onPending();
         break;
    case PROCESSING:
         onProcessing();
         break;
    case PROCESSED:
         onProcessed();
         break;
    default:
         onDefault();
}
Здесь действуют те же правила и подводные камни падения. На первый взгляд, большинство операторов switch с предложением default выглядят достаточно невинно, пока вы не подумаете, что может произойти, когда следующий парень появится и добавит новое значение или два к нашему существующему перечислению статуса. Допустим, он добавляет значение ошибки. Не зная использования нашего перечисления в одном или нескольких операторах switch, он непреднамеренно вызвал бы непреднамеренные совпадения в предложении default из-за отсутствия случая ошибки! Обычно мы этого не хотим, поэтому я рекомендую вам либо не использовать предложение default, либо, еще лучше, заставить его выдать ошибку.

Несколько предостережений

Не злоупотребляйте switch — и, следовательно, не злоупотребляйте if-операторами. Эти условные операторы, когда они используются чрезмерно, печально известны для чрезмерно сложного кода, часто написанного с вложенными операторами if, switch или даже for-loop.

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

Оператор switch не является объектно-ориентированным. В объектно-ориентированном программировании (ООП) есть несколько угловых случаев, когда он подходит для счета, поскольку он быстр и прост в использовании. Это часто случаи, когда у вас было бы только очень мало случаев, составляющих небольшой оператор switch. Однако существует слишком много случаев, когда люди пишут сотни строк кода, составляя один длинный, безумный, трудночитаемый оператор switch. Существуют объектно-ориентированные методы для уменьшения сложности таких утверждений, которые помогают нам выразить то же самое значение. Например, мы можем представить состояние ожидания с одним объектом, состояние обработки с другим и так далее. Я не буду обсуждать это более подробно, потому что эти идеи выходят за рамки этой статьи; в целом, придерживайтесь использования операторов switch для очень небольшого числа случаев.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, уроки по java, java, операторы




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




Анализ алгоритмов: наблюдение
Парсер, чекер и база бесплатных прокси
Старая, старая сказка…