59 votes

Quelle est l'utilisation de default lorsque le switch est pour un enum ?

Supposons que j'aie un enum Color avec 2 valeurs possibles : RED y BLUE :

public enum Color {
    RED,
    BLUE
}

Supposons maintenant que je dispose d'une instruction de commutation pour cette énumération, dans laquelle j'ai du code pour les deux valeurs possibles :

Color color = getColor(); // a method which returns a value of enum "Color"
switch (color) {
case RED:
   ...
   break;

case BLUE:
   ...
   break;

default:
   break;
}

Puisque j'ai un bloc de code pour les deux valeurs possibles de l'énumération, quelle est l'utilisation de default dans le code ci-dessus ?

Dois-je lever une exception si le code atteint d'une manière ou d'une autre la zone default bloc comme celui-ci ?

Color color = getColor(); // a method which returns a value of enum "Color"
switch (color) {
case RED:
   ...
   break;

case BLUE:
   ...
   break;

default:
   throw new IllegalArgumentException("This should not have happened");
}

84voto

Dainesch Points 391

Il est bon de lancer une exception, comme vous l'avez montré dans le deuxième exemple. Vous améliorez la maintenabilité de votre code en échouant rapidement.

Dans ce cas, cela signifie que si vous ajoutez ultérieurement (peut-être des années plus tard) une valeur d'énumération et qu'elle atteint l'instruction switch, vous découvrirez immédiatement l'erreur.

Si la valeur par défaut n'était pas définie, le code pourrait être exécuté même avec la nouvelle valeur de l'énumération et pourrait avoir un comportement indésirable.

53voto

StriplingWarrior Points 56276

Les autres réponses sont correctes en ce qu'elles indiquent que vous devez mettre en œuvre un default qui lève une exception, au cas où une nouvelle valeur serait ajoutée à votre enum dans le futur. Cependant, j'irais même plus loin et je me demanderais pourquoi vous utilisez une méthode de type switch en premier lieu.

Contrairement à des langages comme C++ et C#, Java représente les valeurs Enum comme de véritables objets, ce qui signifie que vous pouvez tirer parti de la programmation orientée objet. Supposons que l'objectif de votre méthode soit de fournir une valeur RVB pour chaque couleur :

switch (color)
    case RED:
       return "#ff0000";
    ...

En fait, si vous voulez que chaque couleur ait une valeur RVB, vous devez l'inclure dans sa description :

public enum Color
{
    RED("#FF0000"),
    BLUE("#0000FF");

    String rgb;
    public Color(String rgb) {
        this.rgb = rgb;
    }
    public getRgb() { return this.rgb; }
}

Ainsi, si vous ajoutez une nouvelle couleur ultérieurement, vous êtes pratiquement obligé de fournir une valeur RVB. C'est encore plus fiable que l'autre approche, car vous échouez à la compilation plutôt qu'à l'exécution.

Notez que vous pouvez faire des choses encore plus compliquées si nécessaire, y compris faire en sorte que chaque couleur fournisse sa propre implémentation d'une méthode abstraite. Les Enums en Java sont vraiment puissants et orientés objet, et dans la plupart des cas, j'ai trouvé que je pouvais éviter d'avoir besoin de switch sur eux en premier lieu.

12voto

Tomáš Piňos Points 762

Pourquoi pas null valeur ?

Ou une classe avec une instruction switch compilée avec une ancienne version de enum et exécutée avec une version plus récente de enum (avec plus de valeurs). C'est un cas courant avec les dépendances de bibliothèques.

Pour de telles raisons, le compilateur considère que l'option switch sans default cas incomplet.

7voto

T.J. Crowder Points 285826

Si vous avez couvert toutes les possibilités avec vos différentes cases et le default ne peut pas se produire, c'est le cas d'utilisation classique de l'outil assertions :

Color color = getColor(); // a method which returns a value of enum "Color"
switch (color) {
    case RED:
       // ...
       break;

    case BLUE:
       // ...
       break;

    default:
       assert false; // This cannot happen
       // or:
       throw new AssertionError("Invalid Colors enum");
}

6voto

Andrew Tobilko Points 1283

Oui, vous devriez le faire. Vous pouvez changer enum mais ne changez pas switch . À l'avenir, cela conduira à des erreurs. Je pense que throw new IllegalArgumentException(msg) est la bonne pratique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X