Зачем нам нужно прерывать заявления о случаях?

Почему компилятор автоматически не помещает инструкции break после каждого блока кода в коммутаторе? Это по историческим причинам? Когда вы хотите выполнить несколько блоков кода?

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

case 'A': case 'B': case 'C': doSomething(); break; case 'D': case 'E': doSomethingElse(); break; 

и т. д. Просто пример.

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

Исторически сложилось так , что дело в том, что в этом case определялась label , также называемая целевой точкой вызова goto . Оператор switch и связанные с ним случаи действительно представляют собой многовекторную ветвь с несколькими потенциальными точками входа в stream кода.

Все, что было сказано, было отмечено почти бесконечное количество раз, что break почти всегда является поведением по умолчанию, которое вы бы предпочли в конце каждого случая.

Java происходит от C, и это синтаксис C.

Бывают случаи, когда несколько операторов case должны иметь только один путь выполнения. Ниже приведен пример, который расскажет вам, сколько дней в месяц.

 class SwitchDemo2 { public static void main(String[] args) { int month = 2; int year = 2000; int numDays = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: numDays = 31; break; case 4: case 6: case 9: case 11: numDays = 30; break; case 2: if ( ((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0) ) numDays = 29; else numDays = 28; break; default: System.out.println("Invalid month."); break; } System.out.println("Number of Days = " + numDays); } } 

Вы можете делать всевозможные интересные вещи с провалом.

Например, скажем, вы хотите сделать определенное действие для всех случаев, но в определенном случае вы хотите сделать это действие плюс что-то еще. Использование оператора switch с провалом сделает его довольно простым.

 switch (someValue) { case extendedActionValue: // do extended action here, falls through to normal action case normalActionValue: case otherNormalActionValue: // do normal action here break; } 

Разумеется, легко забыть оператор break в конце дела и вызвать неожиданное поведение. Хорошие компиляторы будут предупреждать вас, когда вы опускаете оператор break.

Я думаю, что это ошибка. В качестве языковой конструкции так же легко иметь break как и по умолчанию, и вместо этого имеет ключевое слово fallthrough . Большая часть кода, который я написал и прочитал, имеет перерыв после каждого случая.

Почему компилятор автоматически не помещает инструкции break после каждого блока кода в коммутаторе?

Оставляя в стороне хорошее желание иметь возможность использовать идентичный блок для нескольких случаев (который может быть специально обложен) …

Это по историческим причинам? Когда вы хотите выполнить несколько блоков кода?

Это в основном для совместимости с C и, возможно, является древним взломом с древних дней, когда ключевые слова goto бродили по земле. Разумеется, это делает некоторые удивительные вещи, такие как устройство Даффа , но является ли это точкой в ​​его пользу или против … в лучшем случае.

Поэтому вам не нужно повторять код, если вам нужно несколько случаев сделать то же самое:

 case THIS: case THAT: { code; break; } 

Или вы можете делать такие вещи, как:

 case THIS: { do this; } case THAT: { do that; } 

Каскадным способом.

На самом деле ошибка / путаница, если вы спросите меня.

Java является производным от C, чье наследие включает в себя метод, известный как устройство Даффа . Это оптимизация, которая опирается на тот факт, что контроль проваливается от одного случая к другому, в отсутствие break; заявление. К тому времени, когда C был стандартизирован, было много такого кода, как «в дикой природе», и было бы контрпродуктивно менять язык, чтобы разрушить такие конструкции.

Что касается исторической записи, Тони Хоар изобрел деловое заявление в 1960-х годах во время «структурированного программирования». Оператор дела Тони поддерживал несколько ярлыков в каждом случае и автоматический выход без каких-либо вопиющих инструкций break . Требование для явного break было чем-то, что вышло из линии BCPL / B / C. Деннис Ритчи пишет (в ACM HOPL-II):

Например, конечный элемент, который выходит из оператора коммутатора BCPL, не присутствовал на этом языке, когда мы узнали его в 1960-х годах, и поэтому перегрузка ключевого слова break для выхода из оператора B и C переключается на разную эволюцию, а не на сознание изменение.

Я не смог найти никаких исторических трудов о BCPL, но комментарий Ричи говорит о том, что break был более или менее исторической катастрофой. BCPL позже исправил проблему, но, возможно, Ритчи и Томпсон были слишком заняты изобретением Unix, чтобы беспокоиться о такой детали 🙂

Отсутствие автоматического прерывания, добавленного компилятором, позволяет использовать переключатель / case для проверки условий, таких как 1 <= a <= 3 , удалив оператор break из 1 и 2.

 switch(a) { case 1: //I'm between 1 and 3 case 2: //I'm between 1 and 3 case 3: //I'm between 1 and 3 break; } 

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

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

например, используя коды ответов HTTP для аутентификации пользователя с помощью токена времени

код ответа сервера 401 – токен устарел -> регенерировать токен и войти в систему.
серверный код ответа 200 – токен в порядке -> войти в систему.

в случае заявлений:

 case 404: case 500: { Log.v("Server responses","Unable to respond due to server error"); break; } case 401: { //regenerate token } case 200: { // log in user break; } 

Используя это, вам не нужно вызывать функцию входа в систему для ответа 401, потому что когда токен регенерируется, среда выполнения переходит в регистр 200.

Вы можете легко разделить другой тип числа, месяц, число.
Это лучше, если в этом случае;

 public static void spanishNumbers(String span){ span = span.toLowerCase().replace(" ", ""); switch (span){ case "1": case "jan": System.out.println("uno"); break; case "2": case "feb": System.out.println("dos"); break; case "3": case "mar": System.out.println("tres"); break; case "4": case "apr": System.out.println("cuatro"); break; case "5": case "may": System.out.println("cinco"); break; case "6": case "jun": System.out.println("seis"); break; case "7": case "jul": System.out.println("seite"); break; case "8": case "aug": System.out.println("ocho"); break; case "9": case "sep": System.out.println("nueve"); break; case "10": case "oct": System.out.println("diez"); break; } } 

Как говорили люди раньше, нужно разрешить провал, и это не ошибка, это особенность. Если слишком много break утверждений раздражает вас, вы можете легко избавиться от них, используя вместо этого инструкции return . Это на самом деле хорошая практика, потому что ваши методы должны быть как можно меньше (для удобства чтения и ремонтопригодности), поэтому оператор switch уже достаточно велик для метода, следовательно, хороший метод не должен содержать ничего другого, это является примером:

 public class SwitchTester{ private static final Log log = LogFactory.getLog(SwitchTester.class); public static void main(String[] args){ log.info(monthsOfTheSeason(Season.WINTER)); log.info(monthsOfTheSeason(Season.SPRING)); log.info(monthsOfTheSeason(Season.SUMMER)); log.info(monthsOfTheSeason(Season.AUTUMN)); } enum Season{WINTER, SPRING, SUMMER, AUTUMN}; static String monthsOfTheSeason(Season season){ switch(season){ case WINTER: return "Dec, Jan, Feb"; case SPRING: return "Mar, Apr, May"; case SUMMER: return "Jun, Jul, Aug"; case AUTUMN: return "Sep, Oct, Nov"; default: //actually a NullPointerException will be thrown before reaching this throw new IllegalArgumentException("Season must not be null"); } } } 

Исполнение печатает:

 12:37:25.760 [main] INFO lang.SwitchTester - Dec, Jan, Feb 12:37:25.762 [main] INFO lang.SwitchTester - Mar, Apr, May 12:37:25.762 [main] INFO lang.SwitchTester - Jun, Jul, Aug 12:37:25.762 [main] INFO lang.SwitchTester - Sep, Oct, Nov 

как и ожидалось.

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

Представьте, что у вас есть три состояния, которые ждут пользователя, чтобы ввести число, второе для вычисления, а третье – для печати суммы.

В этом случае у вас есть:

  1. State1 – Подождите, пока пользователь вводит номер
  2. State2 – печать суммы
  3. state3 – Рассчитать сумму

Глядя на состояния, вы хотите, чтобы порядок возбуждения начинался с состояния1 , затем с состояния 3 и, наконец, с состоянием2 . В противном случае мы будем печатать только пользовательские данные без вычисления суммы. Чтобы еще раз прояснить это, мы ожидаем, что пользователь введет значение, затем вычислит сумму и распечатает сумму.

Вот пример кода:

 while(1){ switch(state){ case state1: // Wait for user input code state = state3; // Jump to state3 break; case state2: //Print the sum code state = state3; // Jump to state3; case state3: // Calculate the sum code state = wait; // Jump to state1 break; } } в while(1){ switch(state){ case state1: // Wait for user input code state = state3; // Jump to state3 break; case state2: //Print the sum code state = state3; // Jump to state3; case state3: // Calculate the sum code state = wait; // Jump to state1 break; } } 

Если мы не используем break , он будет выполняться в этом порядке, state1 , state2 и state3 . Но используя break , мы избегаем этого сценария и можем заказать в правильной процедуре, которая должна начинаться с state1, а затем state3 и, наконец, не в состоянии state2.

Точно, потому что с некоторым умным размещением вы можете выполнять блоки в каскаде.

  • Java: если vs. Switch
  • Корпус переключателя типа c #
  • Использование двух значений для одного оператора case switch
  • Использование Case / Switch и GetType для определения объекта
  • Ограничения оператора C # - почему?
  • Почему переключатель для enums принимает неявное преобразование в 0, но нет для какого-либо другого целого?
  • Должны ли команды switch всегда содержать предложение по умолчанию?
  • Есть ли лучшая альтернатива этому, чтобы «включить тип»?
  • Scanf не сканирует символ% c, но пропускает утверждение, почему?
  • Как выбрать диапазон значений в инструкции switch?
  • Контроль не может провалиться с одного ярлыка случая
  • Давайте будем гением компьютера.