Utilisation de deux valeurs pour une instruction de casse de commutateur

296

Dans mon code, le programme fait quelque chose en fonction du texte entré par l'utilisateur. Mon code ressemble à:

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

Cependant, le code à l'intérieur des cas text1et text4est le même. Je me demandais donc s'il me serait possible de mettre en œuvre quelque chose comme

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

Je sais que l' ||opérateur ne fonctionnera pas dans l'instruction case, mais y a-t-il quelque chose de similaire que je peux utiliser.

Ankush
la source
32
Être une question fondamentale le rend plus éligible pour les votes positifs si ce n'est pas un doublon car il est largement utile. Et c'est quelque chose qui ne m'est pas venu autant que possible mais maintenant que je le réalise, c'est d'une évidence aveuglante. Donc, dans l'ensemble, un Q&A assez génial
Richard Tingle
1
@RichardTingle - connaissez-vous l'appareil de Duff - en.wikipedia.org/wiki/Duff%27s_device
user93353
4
"Pourquoi tant de votes positifs? Recherchez" java switch "sur Internet et lisez l'une des mille explications." <- que pensez-vous que je faisais?
Brendan
4
J'ai littéralement recherché "plusieurs cas en une seule ligne java" et ce Q&A a été le premier résultat.
domenix
1
La démonstration du commutateur dans la réponse sélectionnée pourrait être reformulée maintenant que JDK-12 a intégré JEP-325. :)
Naman

Réponses:

556

Vous pouvez utiliser les deux CASEinstructions comme suit.

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

VOIR CET EXEMPLE: L'exemple de code calcule le nombre de jours dans un mois particulier:

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

Voici la sortie du code:

Number of Days = 29

TOMBER DANS:

Un autre point d'intérêt est la déclaration de rupture. Chaque instruction break met fin à l'instruction switch englobante. Le flux de contrôle se poursuit avec la première instruction suivant le bloc de commutation. Les instructions break sont nécessaires car sans elles, les instructions dans les blocs de commutation fall through: toutes les instructions après le libellé de cas correspondant sont exécutées en séquence, quelle que soit l'expression des étiquettes de cas suivantes, jusqu'à ce qu'une instruction break soit rencontrée.

EXEMPLE DE CODE:

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

Voici la sortie du code:

August
September
October
November
December

Utilisation de chaînes dans les instructions switch

Dans Java SE 7 et versions ultérieures, vous pouvez utiliser un objet String dans l'expression de l'instruction switch. L'exemple de code suivant,, affiche le numéro du mois en fonction de la valeur de la chaîne nommée month:

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

La sortie de ce code est 8.

DE Java Docs

PSR
la source
Ah d'accord. C'était facile. Je ne savais pas que je pouvais faire ça
Ankush
18
Il convient de mentionner que cette fonctionnalité de langue est appelée fallthrough. Les cas sans breaksont fondamentalement ajoutés au bloc de cas suivant qui est visuellement en dessous, donc tombent .
Empereur Orionii
5
@ Kobor42 apprenez d'abord à parler dans les sites publics. Comment votre suggestion est-elle utile? Merci
PSR
1
@ Kobor42 Que diriez-vous: Pourquoi avez-vous utilisé ce formatage? Mettre des cas à l'horizontale rend le code moins lisible et est généralement considéré comme une mauvaise pratique [Référence facultative mais souhaitée]. J'ai toujours pensé que les instructions switch sont un format particulièrement lisible, mais présentées de cette façon, elles perdent tout cela.
Richard Tingle
2
La démo du commutateur pourrait être reformulée maintenant que JDK-12 a intégré JEP-325. :)
Naman
27

Les casevaleurs sont simplement des points "goto" sans code qui peuvent partager le même point d'entrée:

case text1:
case text4: 
    //blah
    break;

Notez que les accolades sont redondantes.

Bohème
la source
@trig lol. Je fais beaucoup ce genre de choses ces derniers temps - blâmer la saisie au pouce de l'iPhone. Acclamations
Bohème
21

Fais juste

case text1: case text4: 
     do stuff;
     break;
kaljak
la source
15

Avec l'intégration de JEP 325: Switch Expressions (Preview) dans les versions à accès anticipé JDK-12, on peut désormais utiliser la nouvelle forme de l'étiquette de commutateur comme: -

case text1, text4 -> {
     //blah
} 

ou pour reformuler la démo d' une des réponses , quelque chose comme: -

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

Voici comment vous pouvez l'essayer - Compilez une fonction d'aperçu JDK12 avec Maven

Naman
la source
6

Les crochets ne sont pas nécessaires. Fais juste

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

Si quelqu'un est curieux, cela s'appelle un casse-tête. La capacité de le faire est la raison pour laquelle il break;est nécessaire de mettre fin aux déclarations de cas. Pour plus d'informations, consultez l'article wikipedia http://en.wikipedia.org/wiki/Switch_statement .

scottmrogowski
la source
5

Les fallthroughréponses des autres sont bonnes.

Cependant, une autre approche serait d'extraire des méthodes du contenu de vos déclarations de cas, puis d'appeler simplement la méthode appropriée à partir de chaque cas.

Dans l'exemple ci-dessous, la casse 'text1' et la casse 'text4' se comportent de la même manière:

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

Personnellement, je trouve ce style d'écriture des déclarations de cas plus facile à maintenir et légèrement plus lisible, surtout lorsque les méthodes que vous appelez ont de bons noms descriptifs.

Colin D
la source
1
Il n'est pas plus maintenable si text1et text4FAIT PRESQUE CERTAINEMENT la même chose, indépendamment d'un changement futur. S'ils doivent toujours être liés, faire un changement dans le cas de text1(c'est-à-dire changer la méthode qu'il appelle) nécessiterait un changement de text4. Dans ce cas, il n'est évidemment pas plus maintenable. Ça dépend de la situation.
Nick Freeman
1
Je dirai que cette méthode devrait probablement être combinée de toute autre manière, car les instructions switch ne sont pas (à mon humble avis) la plus jolie structure de programmation.
Nick Freeman
5

L'approche de chute est la meilleure que je ressens.

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

Vous pouvez utiliser:

case text1: case text4: 
     do stuff;
     break;
Joseph DSCS
la source
4

Les valeurs de cas sont juste des points "goto" sans code qui peuvent partager le même point d'entrée:

case text1:
case text4: {
// Faire quelque chose de
break;
}

Notez que les accolades sont redondantes.

David_DD
la source
1

JEP 354: Switch Expressions (Preview) dans JDK-13 et JEP 361: Switch Expressions (Standard) dans JDK-14 étendra l' instruction switch afin qu'elle puisse être utilisée comme expression .

Maintenant vous pouvez:

  • attribuer directement une variable à partir d' une expression de commutateur ,
  • utiliser une nouvelle forme d'étiquette de commutateur (case L -> ):

    Le code à droite d'une étiquette de commutateur "case L ->" est limité à une expression, un bloc ou (pour plus de commodité) une instruction throw.

  • utiliser plusieurs constantes par cas, séparées par des virgules,
  • et il n'y a plus de ruptures de valeur :

    Pour générer une valeur à partir d'une expression de commutateur, l' breakinstruction with value est supprimée au profit d'unyield instruction.

La démonstration d' une des réponses pourrait donc ressembler à ceci:

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
la source