JavaRush /Blog Java /Random-FR /Instruction de commutation en Java

Instruction de commutation en Java

Publié dans le groupe Random-FR
Imaginez que vous vous tenez à une fourchette, comme le héros d’un tableau célèbre. Si vous allez à gauche, vous perdrez votre cheval ; si vous allez à droite, vous gagnerez des connaissances. Comment programmer une telle situation ? Vous savez probablement déjà que nous faisons un tel choix en utilisant les constructions if-then et if-then-else .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
Et s'il n'y avait pas deux de ces pistes, mais 10 ? Existe-t-il un chemin « à droite », « un peu à gauche », « un peu plus à gauche » et ainsi de suite, à raison de 10 pièces ? Imaginez comment votre code if-then-else va grandir dans cette version !
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
Ainsi, vous n’avez pas un fork de conditions, mais plusieurs, disons 10 (l’important ici est que le nombre de forks soit limité). Pour de telles situations, il existe un opérateur de sélection spécial - switch case java .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
L'ordre d'exécution dans la déclaration est le suivant :
  • La SelectionExpression est évaluée. Ensuite, l'instruction switch compare l'expression résultante avec la valeur suivante (dans l'ordre indiqué).
  • Si SelectExpression correspond à Value, le code qui suit les deux-points est exécuté.
  • Si la construction break est rencontrée , alors le contrôle est transféré en dehors de la commande switch.
  • Si aucune correspondance entre ExpressionForSelection et Values ​​​​n'est trouvée, le contrôle est transféré au DefaultSelectionCode.
Les points importants
  • Le type SelectionExpression pour une instruction de sélection de commutateur en Java doit être l'un des suivants :

    • octet , court , char , int .
    • Leurs wrappers sont Byte , Short , Character , Integer .
    • Chaîne (depuis Java 7).
    • Énumération ( Enum ).
  • Le bloc par défaut est facultatif, donc si SelectionExpression et Values ​​​​ne correspondent pas, aucune action ne sera effectuée.
  • break est facultatif ; s'il n'est pas présent, le code continuera à s'exécuter (en ignorant les autres comparaisons de valeurs dans les blocs case) jusqu'à la première breakinstruction switch rencontrée ou jusqu'à la fin.
  • s'il est nécessaire d'exécuter le même code pour plusieurs options de sélection, pour éviter les duplications nous indiquons devant lui plusieurs valeurs correspondantes dans des blocs de cas consécutifs .

Passons à la pratique de l'utilisation de l'instruction switch en Java

Ne vous inquiétez pas, nous en avons fini avec la théorie, et après d'autres exemples, tout deviendra beaucoup plus clair. Alors, commençons. Regardons un exemple astronomique concernant les planètes du système solaire. Conformément aux dernières réglementations internationales, nous exclurons Pluton (en raison des propriétés de son orbite). Rappelons que nos planètes sont situées par rapport au Soleil dans l'ordre suivant : Mercure, Vénus, Terre, Mars, Jupiter, Saturne, Uranus et Neptune. Créons une méthode Java qui reçoit en entrée le numéro de série de la planète (par rapport à la distance au Soleil), et en sortie elle donne la composition principale de l'atmosphère de cette planète sous la forme d'une List <String> . Permettez-moi de vous rappeler que certaines planètes ont une composition atmosphérique similaire. Ainsi, Vénus et Mars contiennent principalement du dioxyde de carbone, Jupiter et Saturne sont constitués d'hydrogène et d'hélium, et Uranus et Neptune, en plus de la dernière paire de gaz, contiennent également du méthane. Notre fonction :
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
            break;
        case 2:
        case 4: result.add("Carbon dioxide");
            break;
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
            break;
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
            break;
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
            break;
        default:
            break;
    }
    return result;
}
Attention : nous avons comparé le même code à des planètes ayant des compositions atmosphériques identiques. Et nous l'avons fait en utilisant des constructions de cas consécutifs . Ainsi, si nous voulons obtenir la composition de l’atmosphère de notre planète natale, nous appelons notre méthode avec le paramètre 3 :
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
Expérimentez avec break Que se passe-t-il si nous supprimons toutes les instructions break ? Essayons-le en pratique :
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
        case 2:
        case 4: result.add("Carbon dioxide");
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
        default:
    }
    return result;
}
Si nous imprimons le résultat de la méthode System.out.println(getPlanetAtmosphere(3)), notre planète natale ne sera plus aussi propice à la vie. Ou approprié ? Jugez par vous-même : [Dioxyde de carbone, Azote, Oxygène, Hydrogène, Hélium, Méthane, Hydrogène, Hélium], Pourquoi est-ce arrivé ? Le programme a exécuté tous les cas après la première correspondance et jusqu'à la fin du bloc de commutation.

Pause d'optimisation excessive

Notez que nous pouvons améliorer la méthode avec un arrangement différent des directives break et des options de sélection
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
                break;
        case 3: result.add("Nitrogen");
                result.add("Oxygen");
        case 2:
        case 4: result.add("Carbon dioxide");
                break;
        case 7:
        case 8: result.add("Methane");
        case 5:
        case 6: result.add("Hydrogen");
                result.add("Helium");
    }
     return result;
}
Ça a l'air plus court, n'est-ce pas ? Nous avons réduit le nombre total d'instructions en jouant avec l'ordre des cas et le regroupement. Désormais, chaque type de gaz est ajouté à la liste en une seule ligne de code. La liste du dernier exemple de la méthode est présentée uniquement pour démontrer le travail ; il est fortement déconseillé d'écrire dans un tel style. Si l'auteur (et plus encore les programmeurs tiers) d'un code similaire doit le maintenir, il sera alors très difficile de restaurer la logique de formation des blocs de sélection et du code exécutable pour l'instruction java switch.

Différences avec si

Bien que les instructions if et switch soient d'apparence similaire , n'oubliez pas que l'opérateur à choix multiple switch base le choix des options d'exécution sur une VALEUR SPÉCIFIQUE, alors que dans if. peut être n’importe quelle expression logique. Tenez compte de ce fait lors de la conception de votre code. Examinons de plus près les innovations apportées au switch dans les différentes versions de Java.

Changer en Java 7

Avant Java 7, les primitives byte, short, char et int pouvaient être utilisées comme valeur pour un commutateur. Il existe également un support pour les énumérations et les wrappers des types primitifs répertoriés ci-dessus : Caractère, Octet, Short et Integer. Mais nous avons souvent besoin de trouver la valeur d’une chaîne de commutateur Java ! Voici à quoi cela ressemblerait dans Java 6 :
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
Et énumération :
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
Mais à partir de Java 7, il était possible d'utiliser le type String comme valeur pour un commutateur :
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
Malgré les nouvelles fonctionnalités, l'approche utilisant l'énumération est plus flexible et son utilisation est recommandée : nous pouvons réutiliser cette énumération plusieurs fois.

Changer en Java 12

Java 12 a amélioré les expressions Switch pour la correspondance de modèles. Si nous utilisons Switch comme dans l'exemple ci-dessus, pour définir la valeur d'une variable, nous devons calculer la valeur et l'attribuer à la variable donnée, puis utiliser break :
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
Mais grâce aux capacités de Java 12, nous pouvons réécrire cette expression comme suit :
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
Passons en revue un peu les changements :
  1. Si auparavant nous définissions une valeur variable à l'intérieur des blocs case, puisque l'instruction switch elle-même ne pouvait rien renvoyer, nous avons maintenant une telle opportunité et nous renvoyons directement la valeur en utilisant switch.

  2. Auparavant, nous ne pouvions plus avoir quoi que ce soit à droite de break, mais maintenant nous l'utilisons comme instruction return pour renvoyer la valeur de notre switch. Les deux points marquent le point d’entrée dans un bloc d’instructions. Autrement dit, à partir de ce moment, l'exécution de tout le code ci-dessous commence, même lorsqu'une autre étiquette est rencontrée.

    Le résultat est une transition de bout en bout d’une marque à l’autre, également appelée transition .

Instruction Switch en Java - 2Pour réaliser une telle passe, vous devez soit parcourir complètement tous les éléments, soit utiliser break ou return. L'innovation de Java 12 nous donne la possibilité d'utiliser l'opérateur lambda, ce qui garantit que seul le code à sa droite sera exécuté. Sans aucun « échec ». À quoi ressemblera l’exemple précédent dans ce cas :
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
Le code est devenu beaucoup plus simple, n'est-ce pas ? Et encore une chose : l'opérateur lambda peut également servir d'analogue typique d'un deux-points, après quoi il y a un bloc entier avec quelques opérations :
int count = 2;
int value = switch (count) {
  case 1 -> {
     //some computational operations...
     break 12;
  }
  case 2 -> {
     //some computational operations...
     break 32;
  }
  case 3 -> {
     //some computational operations...
     break 52;
  }
  default -> {
     //some computational operations...
     break 0;
  }
};
Et si, dans certains cas, la valeur de retour était la même ? Il s’avère que nous avons en fait les mêmes cas pour des valeurs différentes. Voici comment cela pourrait être raccourci grâce aux nouvelles fonctionnalités de Java 12 :
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Changer en Java 13

Dans Java 13, la façon dont un commutateur renvoie une valeur a changé. Si dans Java 12 nous avons écrit la valeur de retour après break, qui nous a servi de retour pour le bloc switch, nous renverrons maintenant la valeur en utilisant le mot rendement . Regardons:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
Dans le même temps, le code écrit en Java 12 utilisant break pour return ne sera pas compilé (( Instruction Switch en Java - 3Break sera utilisé, mais dans les situations où nous n'avons pas besoin de retourner quoi que ce soit.

Total

  • Utilisez l' instruction case lorsqu'il y a plus de deux branches pour éviter d'encombrer votre code avec des structures if.
  • N'oubliez pas de terminer le bloc logique de chaque branche correspondant à une valeur précise (bloc case) par un appel break .
  • En plus de certains types primitifs, l'instruction switch peut également utiliser les types Enum et String comme expressions .
  • N'oubliez pas le bloc par défaut : utilisez-le pour gérer les valeurs de sélection non planifiées.
  • Pour optimiser les performances, déplacez les branches de code avec les choix les plus courants au début du bloc switch.
  • Ne vous laissez pas emporter par « l'optimisation » en supprimant le saut à la fin du bloc de sélection de cas - un tel code est difficile à comprendre et, par conséquent, difficile à maintenir pendant son développement.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION