Używanie dwóch wartości dla jednej instrukcji case switch


295

W moim kodzie program robi coś w zależności od tekstu wprowadzonego przez użytkownika. Mój kod wygląda następująco:

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

Jednak kod w przypadku text1i text4jest taki sam. Zastanawiałem się zatem, czy byłoby możliwe wdrożenie czegoś takiego

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

Wiem, że ||operator nie będzie działał w instrukcji case, ale czy mogę użyć czegoś podobnego.


32
Bycie podstawowym pytaniem sprawia, że ​​jest bardziej kwalifikowalne do głosowania, jeśli nie jest duplikatem, ponieważ jest bardzo przydatne. I to jest coś, co nie zdarzyło mi się tak dokładnie, jak to możliwe, ale teraz, kiedy zdaję sobie sprawę, jest to zupełnie oczywiste. Podsumowując, całkiem niesamowite pytania i odpowiedzi
Richard Tingle

1
@RichardTingle - czy znasz urządzenie Duffa - en.wikipedia.org/wiki/Duff%27s_device
user93353

4
„Po co tyle głosów poparcia? Wyszukaj„ java switch ”w Internecie i przeczytaj jedno z tysiąca wyjaśnień.” <- jak myślisz, co robiłem?
Brendan,

4
Dosłownie szukałem „wielu przypadków w jednej linii java” i to pytanie było pierwszym rezultatem.
domenix

1
Demo przełącznika w wybranej odpowiedzi może zostać przeformułowane teraz, gdy JDK-12 zintegrował JEP-325. :)
Naman

Odpowiedzi:


555

Możesz użyć obu CASEinstrukcji w następujący sposób.

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

ZOBACZ TEN PRZYKŁAD: Przykład kodu oblicza liczbę dni w danym miesiącu:

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);
    }
}

To jest wynik kodu:

Number of Days = 29

PRZESZŁOŚĆ:

Kolejnym interesującym punktem jest zestawienie przerw. Każda instrukcja break kończy dołączoną instrukcję switch. Przepływ sterowania jest kontynuowany z pierwszą instrukcją po bloku przełącznika. Instrukcje break są konieczne, ponieważ bez nich instrukcje w blokach przełącznikówfall through : Wszystkie instrukcje po dopasowanej etykiecie sprawy są wykonywane po kolei, niezależnie od wyrażenia kolejnych etykiet sprawy, aż do napotkania instrukcji break.

PRZYKŁADOWY KOD:

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);
            }
        }
    }
}

To jest wynik kodu:

August
September
October
November
December

Używanie ciągów w instrukcjach przełączania

W Javie SE 7 i nowszych można użyć obiektu String w wyrażeniu instrukcji switch. Poniższy przykład kodu wyświetla liczbę miesiąca na podstawie wartości ciągu o nazwie miesiąc:

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);
        }
    }
}

Dane wyjściowe z tego kodu to 8.

Z dokumentów Java


o ok To było łatwe. Nie wiedziałem, że mogę to zrobić
Ankush

18
Warto wspomnieć, że ta funkcja języka nazywa się przewrotnością. Obudowy bez breaksą w zasadzie dołączane z kolejnym blokiem skrzynek, który jest wizualnie poniżej, dlatego spada .
Cesarz Orionii

5
@ Kobor42 najpierw dowiedz się, jak rozmawiać na stronach publicznych. Jaka jest twoja sugestia, aby pomóc w pełni. Dzięki
PSR

1
@ Kobor42 Co powiesz na: Dlaczego użyłeś tego formatowania? Umieszczanie przypadków poziomo powoduje, że kod jest mniej czytelny i jest ogólnie uważany za złą praktykę [Odniesienie opcjonalne, ale pożądane]. Zawsze uważałem, że instrukcje switch są szczególnie czytelnym formatem, ale przedstawione w ten sposób tracą to wszystko.
Richard Tingle,

2
Demo przełącznika może zostać przeformułowane teraz, gdy JDK-12 zintegrował JEP-325. :)
Naman


27

Te casewartości są tylko Bezkodowe punkty „goto”, które mogą dzielić ten sam punkt wejścia:

case text1:
case text4: 
    //blah
    break;

Zauważ, że nawiasy klamrowe są zbędne.


@trig lol. Ostatnio często coś takiego robię - obwinianie pisania kciukiem iPhone'a. Na zdrowie
czeski


15

Dzięki integracji JEP 325: wyrażenia przełączników (wersja zapoznawcza) w kompilacjach wczesnego dostępu JDK-12 można teraz korzystać z nowej formy etykiety przełącznika jako:

case text1, text4 -> {
     //blah
} 

lub przeformułować demo z jednej z odpowiedzi , coś w stylu: -

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);
    }
}

Oto, jak możesz spróbować - Skompiluj funkcję podglądu JDK12 za pomocą Maven


6

Nawiasy są niepotrzebne. Po prostu zrób

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

Jeśli ktoś jest ciekawy, nazywa się to przypadkiem. Zdolność do tego jest powodem, dla którego break;konieczne jest zakończenie instrukcji case. Aby uzyskać więcej informacji, zobacz artykuł w Wikipedii http://en.wikipedia.org/wiki/Switch_statement .


5

The fallthrough odpowiedzi Pozostałe są dobre.

Jednak innym podejściem byłoby wyodrębnienie metod z treści instrukcji przypadku, a następnie po prostu wywołanie odpowiedniej metody z każdego przypadku.

W poniższym przykładzie zarówno wielkość liter „text1”, jak i wielkość liter „text4” zachowują się tak samo:

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

Osobiście uważam, że ten styl pisania instrukcji jest łatwiejszy w utrzymaniu i nieco bardziej czytelny, szczególnie gdy metody, które wywołujesz, mają dobre opisowe nazwy.


1
Nie jest łatwiejsze do utrzymania, jeśli text1i text4ZAWSZE PRAWIE zrobi to samo, niezależnie od przyszłych zmian. Jeśli zawsze powinny być połączone, dokonanie zmiany w przypadku text1(co oznacza zmianę wywoływanej metody) wymagałoby zmiany text4. W tym przypadku nie jest to oczywiście łatwiejsze w utrzymaniu. To zależy od sytuacji.
Nick Freeman

1
Powiem, że ta metoda i tak powinna być prawdopodobnie połączona w inny sposób, ponieważ instrukcje switch nie są (IMHO) najładniejszą strukturą programowania.
Nick Freeman

5

Podejście Falling jest najlepsze, jakie czuję.

case text1:
case text4: {
        //Yada yada
        break;
} 


4

Wartości przypadków są po prostu bezkodowymi punktami „goto”, które mogą dzielić ten sam punkt wejścia:

case
text1 : case text4: {
// Zrób coś zepsutego
;
}

Zauważ, że nawiasy klamrowe są zbędne.


1

JEP 354: Przełącz wyrażenia ( wersja zapoznawcza) w JDK-13 i JEP 361: Przełącz wyrażenia (Standard) w JDK-14 rozszerzy instrukcję przełączania, aby mogła być używana jako wyrażenie .

Teraz możesz:

  • bezpośrednio przypisz zmienną z wyrażenia przełącznika ,
  • użyj nowej formy etykiety przełącznika (case L -> ):

    Kod po prawej stronie etykiety przełącznika „case L ->” jest ograniczony do wyrażenia, bloku lub (dla wygody) instrukcji throw.

  • użyj wielu stałych na przypadek, oddzielonych przecinkami,
  • a także nie ma już podziałów wartości :

    Aby uzyskać wartość z wyrażenia przełączającego, instrukcja breakwith value jest upuszczana na korzyść yieldinstrukcji.

Demo jednej z odpowiedzi może wyglądać następująco:

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);
  }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.