Verwenden von zwei Werten für eine switch case-Anweisung

295

In meinem Code macht das Programm etwas abhängig von dem vom Benutzer eingegebenen Text. Mein Code sieht aus wie:

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

Der Code in Fällen text1und text4ist jedoch der gleiche. Ich habe mich daher gefragt, ob es mir möglich sein würde, so etwas umzusetzen

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

Ich weiß, dass der ||Operator in der case-Anweisung nicht funktioniert, aber es gibt etwas Ähnliches, das ich verwenden kann.

Ankush
quelle
32
Wenn es sich um eine grundlegende Frage handelt, ist es eher für Upvotes geeignet, wenn es kein Duplikat ist, da es allgemein nützlich ist. Und es ist etwas, das mir nicht so gut wie möglich eingefallen ist, aber jetzt, wo ich es merke, ist es blendend offensichtlich. Alles in allem also ein ziemlich tolles Q & A
Richard Tingle
1
@ RichardTingle - sind Sie mit Duffs Gerät vertraut - en.wikipedia.org/wiki/Duff%27s_device
user93353
4
"Warum so viele Upvotes? Suchen Sie im Internet nach" Java Switch "und lesen Sie eine der tausend Erklärungen." <- was denkst du habe ich gemacht?
Brendan
4
Ich habe buchstäblich nach "mehreren Fällen in einer Zeile Java" gesucht und diese Fragen und Antworten waren das erste Ergebnis.
Domenix
1
Die Switch-Demo in der ausgewählten Antwort könnte jetzt umformuliert werden , da JDK-12 JEP-325 integriert hat. :)
Naman

Antworten:

555

Sie können beide CASEAnweisungen wie folgt verwenden.

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

SIEHE DIESES BEISPIEL: Das Codebeispiel berechnet die Anzahl der Tage in einem bestimmten Monat:

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

Dies ist die Ausgabe des Codes:

Number of Days = 29

DURCHFALLEN:

Ein weiterer interessanter Punkt ist die break-Anweisung. Jede break-Anweisung beendet die einschließende switch-Anweisung. Der Kontrollfluss wird mit der ersten Anweisung nach dem Schalterblock fortgesetzt. Die break-Anweisungen sind erforderlich, da ohne sie Anweisungen in switch-Blöcken fall through: Alle Anweisungen nach der übereinstimmenden case-Bezeichnung werden unabhängig vom Ausdruck nachfolgender case-Bezeichnungen nacheinander ausgeführt, bis eine break-Anweisung auftritt.

BEISPIELCODE:

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

Dies ist die Ausgabe des Codes:

August
September
October
November
December

Verwenden von Strings in switch-Anweisungen

In Java SE 7 und höher können Sie ein String-Objekt im Ausdruck der switch-Anweisung verwenden. Das folgende Codebeispiel zeigt die Nummer des Monats basierend auf dem Wert der Zeichenfolge mit dem Namen month an:

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

Die Ausgabe dieses Codes ist 8.

VON Java Docs

PSR
quelle
Oh ok. Das war einfach. Ich wusste nicht, dass ich das tun kann
Ankush
18
Es ist erwähnenswert, dass diese Sprachfunktion als Fallthrough bezeichnet wird. Fälle ohne breakwerden grundsätzlich an den nächsten Fallblock angehängt, der sich visuell darunter befindet, und fallen daher durch.
Kaiser Orionii
5
@ Kobor42 lernen zuerst, wie man auf öffentlichen Seiten spricht. Wie auch immer, Ihr Vorschlag ist hilfreich. Danke
PSR
1
@ Kobor42 Wie wäre es mit: Warum haben Sie diese Formatierung verwendet? Das horizontale Setzen von Fällen macht den Code weniger lesbar und wird im Allgemeinen als schlechte Praxis angesehen [Referenz optional, aber erwünscht]. Ich hatte immer das Gefühl, dass switch-Anweisungen ein besonders lesbares Format sind, aber auf diese Weise dargestellt, verlieren sie all das.
Richard Tingle
2
Die Switch-Demo könnte jetzt umformuliert werden , da JDK-12 JEP-325 integriert hat. :)
Naman
27

Die caseWerte sind nur codelose "goto" -Punkte, die denselben Einstiegspunkt haben können:

case text1:
case text4: 
    //blah
    break;

Beachten Sie, dass die geschweiften Klammern redundant sind.

Böhmisch
quelle
@ Trig lol. Ich mache so etwas in letzter Zeit oft - ich beschuldige das Tippen des iPhone-Daumens. Cheers
Bohemian
21

Mach einfach

case text1: case text4: 
     do stuff;
     break;
Kaljak
quelle
15

Mit der Integration von JEP 325: Switch Expressions (Vorschau) in JDK-12-Builds für den frühen Zugriff kann die neue Form des Switch-Labels jetzt wie folgt verwendet werden:

case text1, text4 -> {
     //blah
} 

oder um die Demo aus einer der Antworten neu zu formulieren , so etwas wie: -

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

So können Sie es ausprobieren: Kompilieren Sie eine JDK12-Vorschaufunktion mit Maven

Naman
quelle
6

Die Klammern sind nicht erforderlich. Mach einfach

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

Wenn jemand neugierig ist, spricht man von einem Fallfall. Die Fähigkeit, dies zu tun, ist der Grund, warum break;es notwendig ist, Fallaussagen zu beenden. Weitere Informationen finden Sie im Wikipedia-Artikel http://en.wikipedia.org/wiki/Switch_statement .

Scottmrogowski
quelle
5

Die fallthroughAntworten anderer sind gut.

Ein anderer Ansatz wäre jedoch, Methoden aus dem Inhalt Ihrer case-Anweisungen zu extrahieren und dann einfach die entsprechende Methode aus jedem Fall aufzurufen.

Im folgenden Beispiel verhalten sich Fall 'Text1' und Fall 'Text4' gleich:

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

Ich persönlich finde diese Art des Schreibens von Fallaussagen wartbarer und etwas lesbarer, insbesondere wenn die von Ihnen aufgerufenen Methoden gute beschreibende Namen haben.

Colin D.
quelle
1
Es ist nicht wartbarer, wenn text1und text4wird fast das Gleiche tun, unabhängig von einer zukünftigen Änderung. Wenn sie immer verknüpft sein sollten, würde eine Änderung des Falls für text1(dh das Ändern der aufgerufenen Methode) eine Änderung in erfordern text4. In diesem Fall ist es offensichtlich nicht mehr wartbar. Es hängt von der Situation ab.
Nick Freeman
1
Ich werde sagen, dass diese Methode wahrscheinlich sowieso mit der anderen kombiniert werden sollte, da switch-Anweisungen nicht (IMHO) die schönste Programmierstruktur sind.
Nick Freeman
5

Fall-through-Ansatz ist der beste, den ich fühle.

case text1:
case text4: {
        //Yada yada
        break;
} 
Ankur Sharma
quelle
5

Sie können verwenden:

case text1: case text4: 
     do stuff;
     break;
Joseph DSCS
quelle
4

Die Fallwerte sind nur codelose "goto" -Punkte, die denselben Einstiegspunkt haben können:

case text1:
case text4: {
// Mach etwas
kaputt;
}}

Beachten Sie, dass die geschweiften Klammern redundant sind.

David_DD
quelle
1

JEP 354: Switch-Ausdrücke (Vorschau) in JDK-13 und JEP 361: Switch-Ausdrücke (Standard) in JDK-14 erweitern die switch-Anweisung, sodass sie als Ausdruck verwendet werden kann .

Jetzt kannst du:

  • Variable direkt aus Schalterausdruck zuweisen ,
  • Verwenden Sie eine neue Form der Schalterbezeichnung ( case L ->):

    Der Code rechts von der Schalterbezeichnung "case L ->" ist auf einen Ausdruck, einen Block oder (der Einfachheit halber) eine throw-Anweisung beschränkt.

  • Verwenden Sie mehrere durch Kommas getrennte Konstanten pro Fall.
  • und es gibt auch keine wertebrüche mehr :

    Um einen Wert aus einem switch-Ausdruck zu erhalten, wird die breakwith-value-Anweisung zugunsten einer yieldAnweisung gelöscht .

Die Demo aus einer der Antworten könnte also so aussehen:

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);
  }
}
Iskuskov Alexander
quelle