Використання двох значень для одного оператора випадку перемикача


295

У моєму коді програма робить щось залежно від тексту, введеного користувачем. Мій код виглядає так:

switch (name) {
        case text1: {
            //blah
            break;
        }
        case text2: {
            //blah
            break;
        }
        case text3: {
            //blah
            break;
        }
        case text4: {
            //blah
            break;
        }

Однак код всередині справ text1і text4той самий. Тому мені було цікаво, чи вдасться мені реалізувати щось подібне

case text1||text4: {
            //blah
            break;
        }

Я знаю, що ||оператор не буде працювати в заяві справи, але чи можу я використати щось подібне.


32
Основне питання робить його, якщо що-небудь більш придатне для анонсів, якщо це не дублікат, як його широка корисність. І це щось таке, що не сталося для мене якомога можливішим, але тепер, коли я усвідомлюю це його сліпуче очевидне. Таким чином, загалом надзвичайний Q&A
Річард Тінгл

1
@RichardTingle - ви знайомі з пристроєм Даффа - en.wikipedia.org/wiki/Duff%27s_device
користувач93353

4
"Чому так багато грошей? Знайдіть" java switch "в Інтернеті і прочитайте одну з тисяч пояснень." <- що ти думаєш, що я робив?
Брендан

4
Я буквально шукав "кілька випадків в одній лінійці Java", і це запитання було першим результатом.
domenix

1
Демонстраційний перемикач у вибраній відповіді можна перефразувати тепер, коли JDK-12 інтегрував JEP-325. :)
Наман

Відповіді:


555

Ви можете використовувати є обидва CASEтвердження наступним чином.

  case text1: 
  case text4:{
            //blah
            break;
        }

ДИВІТЬСЬКИЙ ПРИКЛАД: Приклад коду обчислює кількість днів у конкретному місяці:

class SwitchDemo {
    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);
    }
}

Це вихід з коду:

Number of Days = 29

ПРОВАЛЮВАТИСЯ:

Ще одна цікава точка - заява про перерву. Кожен випадок перерви закінчує констатуючу операцію перемикача. Контрольний потік продовжується з першого твердження за блоком комутатора. Оперативні перерви необхідні, оскільки без них оператори в блоках комутаторів fall through: Усі оператори після відповідних міток регістру виконуються послідовно, незалежно від виразу наступних міток регістру, доки не з’явиться оператор перерви.

ПРИКЛАД КОДУ:

public class SwitchFallThrough {

    public static void main(String[] args) {
        java.util.ArrayList<String> futureMonths =
            new java.util.ArrayList<String>();

        int month = 8;

        switch (month) {
            case 1:  futureMonths.add("January");
            case 2:  futureMonths.add("February");
            case 3:  futureMonths.add("March");
            case 4:  futureMonths.add("April");
            case 5:  futureMonths.add("May");
            case 6:  futureMonths.add("June");
            case 7:  futureMonths.add("July");
            case 8:  futureMonths.add("August");
            case 9:  futureMonths.add("September");
            case 10: futureMonths.add("October");
            case 11: futureMonths.add("November");
            case 12: futureMonths.add("December");
            default: break;
        }

        if (futureMonths.isEmpty()) {
            System.out.println("Invalid month number");
        } else {
            for (String monthName : futureMonths) {
               System.out.println(monthName);
            }
        }
    }
}

Це вихід з коду:

August
September
October
November
December

Використання рядків у операторах переключення

У Java SE 7 та новіших версіях ви можете використовувати об'єкт String у виразі перемикача. У наведеному нижче прикладі коду відображається номер місяця, виходячи зі значення рядка, названого місяцем:

public class StringSwitchDemo {

    public static int getMonthNumber(String month) {

        int monthNumber = 0;

        if (month == null) {
            return monthNumber;
        }

        switch (month.toLowerCase()) {
            case "january":
                monthNumber = 1;
                break;
            case "february":
                monthNumber = 2;
                break;
            case "march":
                monthNumber = 3;
                break;
            case "april":
                monthNumber = 4;
                break;
            case "may":
                monthNumber = 5;
                break;
            case "june":
                monthNumber = 6;
                break;
            case "july":
                monthNumber = 7;
                break;
            case "august":
                monthNumber = 8;
                break;
            case "september":
                monthNumber = 9;
                break;
            case "october":
                monthNumber = 10;
                break;
            case "november":
                monthNumber = 11;
                break;
            case "december":
                monthNumber = 12;
                break;
            default: 
                monthNumber = 0;
                break;
        }

        return monthNumber;
    }

    public static void main(String[] args) {

        String month = "August";

        int returnedMonthNumber =
            StringSwitchDemo.getMonthNumber(month);

        if (returnedMonthNumber == 0) {
            System.out.println("Invalid month");
        } else {
            System.out.println(returnedMonthNumber);
        }
    }
}

Вихід з цього коду дорівнює 8.

ВІД Java Документів


о, добре. Це було легко. Не знав, що я можу це зробити
Анкуш

18
Варто зазначити, що ця мовна особливість називається переломною. Справи без breakв основному додаються до наступного блоку корпусів, який візуально внизу, отже, пропадає .
Імператор Оріоній

5
@ Kobor42 спочатку дізнайся, як розмовляти на загальнодоступних сайтах. Кожен, як пропонується твоя пропозиція ful.Thanks
PSR

1
@ Kobor42 Як щодо: Чому ви використовували це форматування? Наведення випадків на хорізонталі робить код менш читабельним і, як правило, вважається поганою практикою [Довідка необов'язкова, але бажана]. Я завжди відчував, що заяви про перемикання - це особливо читабельний формат, але представлені таким чином вони втрачають все це.
Річард Тінгл

2
Демо-вимикач можна переформулювати тепер, коли JDK-12 вбудував JEP-325. :)
Наман


27

Ці caseзначення - це просто кодові "goto" точки, які можуть мати однакову точку входу:

case text1:
case text4: 
    //blah
    break;

Зауважте, що брекети є зайвими.


@trig lol. Займаюсь подібними справами останнім часом - звинувачую в натисканні пальцем iPhone. Ура
богем


15

Завдяки інтеграції JEP 325: Switch Expressions (Попередній перегляд) в ранньому доступі JDK-12 тепер можна використовувати нову форму мітки комутатора як: -

case text1, text4 -> {
     //blah
} 

або перефразовувати демонстрацію з однієї з відповідей , наприклад:

public class RephraseDemo {

    public static void main(String[] args) {
        int month = 9;
        int year = 2018;
        int numDays = 0;

        switch (month) {
            case 1, 3, 5, 7, 8, 10, 12 ->{
                numDays = 31;
            }
            case 4, 6, 9, 11 ->{
                numDays = 30;
            }
            case 2 ->{
                if (((year % 4 == 0) &&
                        !(year % 100 == 0))
                        || (year % 400 == 0))
                    numDays = 29;
                else
                    numDays = 28;
            }
            default ->{
                System.out.println("Invalid month.");

            }
        }
        System.out.println("Number of Days = " + numDays);
    }
}

Ось як можна спробувати - Скомпілюйте функцію попереднього перегляду JDK12 за допомогою Maven


6

Дужки непотрібні. Просто роби

case text1:
case text4:
  doSomethingHere();
  break;
case text2:
  doSomethingElse()
  break;

Якщо хтось цікавий, це називається падінням справи. Здатність робити це є причиною, чому break;необхідно закінчувати заяви справи. Для отримання додаткової інформації дивіться статтю wikipedia http://en.wikipedia.org/wiki/Switch_statement .


5

Ці fallthroughвідповіді на інші є хорошими.

Однак іншим підходом є вилучення методів із вмісту заяв про справу, а потім просто виклик відповідного методу з кожного випадку.

У наведеному нижче прикладі і регістр 'text1' і case 'text4' поводяться однаково:

switch (name) {
        case text1: {
            method1();
            break;
        }
        case text2: {
            method2();
            break;
        }
        case text3: {
            method3();
            break;
        }
        case text4: {
            method1();
            break;
        }

Мені особисто здається, що цей стиль написання випадок у справах є більш зрозумілим і трохи читабельнішим, особливо коли методи, які ви називаєте, мають хороші описові назви.


1
Це не є більш реальним, якщо text1і text4буде НАРОДНО ВІДПОВІДНО робити те саме, незалежно від майбутніх змін. Якщо вони завжди мають бути пов’язані між собою, внесення змін у випадку для text1(означає зміну методу, який він викликає) вимагатиме зміни text4. У цьому випадку це, очевидно, не є більш ретельним. Це залежить від ситуації.
Нік Фріман

1
Я скажу, що цей метод, мабуть, в будь-якому випадку повинен поєднуватися з іншим способом, оскільки заяви комутатора не є (IMHO) найкрасивішою структурою програмування.
Нік Фріман



4

Значення регістру - це просто кодові "goto" точки, які можуть мати однакову точку входу:

case text1:
text text4: {
// Зроби щось
;
}

Зауважте, що брекети є зайвими.


1

JEP 354: Перемикання виразів (попередній перегляд) в JDK-13 та JEP 361: Вираження комутації (стандартні) в JDK-14 розширить оператор перемикання, щоб його можна було використовувати як вираз .

Тепер ти можеш:

  • безпосередньо призначити змінну з виразу перемикача ,
  • використовувати нову форму мітки перемикача ( case L ->):

    Код праворуч від мітки перемикача "case L ->" може бути виразом, блоком або (для зручності) оператором кидка.

  • використовувати кілька констант на випадок, розділені комами,
  • а також більше немає перерв на значення :

    Щоб отримати значення з виразу перемикача, breakоператор зі значенням знижується на користь yieldоператора.

Отже, демонстрація однієї з відповідей може виглядати приблизно так:

public class SwitchExpression {

  public static void main(String[] args) {
      int month = 9;
      int year = 2018;
      int numDays = switch (month) {
        case 1, 3, 5, 7, 8, 10, 12 -> 31;
        case 4, 6, 9, 11 -> 30;
        case 2 -> {
          if (java.time.Year.of(year).isLeap()) {
            System.out.println("Wow! It's leap year!");
            yield 29;
          } else {
            yield 28;
          }
        }
        default -> {
          System.out.println("Invalid month.");
          yield 0;
        }
      };
      System.out.println("Number of Days = " + numDays);
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.