Java utilisant enum avec instruction switch


106

J'ai regardé plusieurs questions / réponses sur SO similaires à cette question mais je n'ai pas trouvé de solution.

Ce que j'ai est une énumération qui représente différentes façons d'afficher un guide TV ...

Dans la Applicationclasse NDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... lorsque l'utilisateur change la vue, un gestionnaire d'événements reçoit un intde 0 à 2 et j'aimerais faire quelque chose comme ça ...

Dans un Activity onClick(DialogInterface dialog, int which)gestionnaire d'événements Android

// 'which' is an int from 0-2
switch (which) {
    case NDroid.guideView.GUIDE_VIEW_SEVEN_DAY:
    ...
    break;
}

Je suis habitué aux énumérations C # et aux instructions select / case qui permettraient quelque chose comme ce qui précède et je sais que Java fait les choses différemment, mais je ne peux tout simplement pas comprendre ce que je dois faire.

Vais-je devoir recourir aux ifdéclarations? Il n'y aura probablement que 3 choix, donc je pourrais le faire, mais je me suis demandé comment cela pouvait être fait avec switch-case en Java.

EDIT Désolé, je n'ai pas complètement développé le problème car je le considérais comme un problème Java générique. J'ai ajouté à la question pour expliquer un peu plus.

Il n'y a rien de spécifique à Android, c'est pourquoi je ne l'ai pas étiqueté comme Android, mais l'énumération est définie dans la Applicationclasse et le code où je ne veux pas que le commutateur se trouve dans un Activity. L'énumération est statique car je dois y accéder à partir de plusieurs activités.


1
Devrait être juste case GUIDE_VIEW_SEVEN_DAYaprès des importations appropriées; quel (s) problème (s) rencontrez-vous?
Dave Newton

Ne pouvez-vous pas simplement faire en sorte que votre gestionnaire d'événements reçoive une énumération? En dehors de cela, cela aidera peut-être: stackoverflow.com/questions/5292790/…
Brian Roach

@Dave: Oups désolé, j'ai corrigé le code pour montrer comment c'est. Eclipse me donne une erreur de type Mismatch indiquant qu'il ne peut pas convertir de guideView en int.
Squonk

@Brian: Ceci est une application Android et le gestionnaire d'événements ( OnClickListener ) est défini par l' DialogInterfaceinterface que je dois implémenter.
Squonk

@MisterSquonk Oh, vous m'avez manqué de l'obtenir d'un int - désolé, voyez la réponse d'Ophidian, bien que j'aie mis la fonctionnalité dans l'énumération.
Dave Newton

Réponses:


162

La partie qui vous manque est la conversion de l'entier vers l'énumération de type sécurisé. Java ne le fera pas automatiquement. Il existe plusieurs façons de procéder:

  1. Utilisez une liste d'entiers finaux statiques plutôt qu'une énumération de type sécurisé et activez la valeur int que vous recevez (c'est l'approche pré-Java 5)
  2. Activez soit une valeur d'ID spécifiée (comme décrit par heneryville ), soit la valeur ordinale des valeurs d'énumération; c'est à direguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Déterminez la valeur enum représentée par la valeur int, puis activez la valeur enum.

    enum GuideView {
        SEVEN_DAY,
        NOW_SHOWING,
        ALL_TIMESLOTS
    }
    
    // Working on the assumption that your int value is 
    // the ordinal value of the items in your enum
    public void onClick(DialogInterface dialog, int which) {
        // do your own bounds checking
        GuideView whichView = GuideView.values()[which];
        switch (whichView) {
            case SEVEN_DAY:
                ...
                break;
            case NOW_SHOWING:
                ...
                break;
        }
    }

    Vous pouvez trouver plus utile / moins sujet aux erreurs d'écrire une valueOfimplémentation personnalisée qui prend vos valeurs entières comme argument pour résoudre la valeur d'énumération appropriée et vous permet de centraliser votre vérification des limites.


Merci beaucoup. Il m'a fallu un certain temps pour l'intégrer à mon code, mais cela fonctionne bien maintenant avec l'exemple de code que vous avez publié. 6 ans avec C # et 1 an avec Java - ce n'est pas souvent que je rencontre quelque chose qui me dérange. Tant de similitudes mais occasionnelles comme celle-ci qui est tellement différente. Je n'oublierai pas celui-ci à la hâte. :-)
Squonk

2
Vous avez besoin des noms d'énumération non qualifiés dans l'instruction case, donc case GuideView.SEVEN_DAY:donne une erreur de compilation, cela devrait être case SEVEN_DAY:.
haridsv

C'est superbe frère !!
Neo

42

Si whichViewest un objet de GuideView Enum, ce qui suit fonctionne bien. Veuillez noter qu'il n'y a pas de qualificatif pour la constante après case.

switch (whichView) {
    case SEVEN_DAY:
        ...
        break;
    case NOW_SHOWING:
        ...
        break;
}

4
Comment est-ce possible?!
Jes Chergui

12

Les énumérations ne doivent pas être qualifiées dans l'étiquette de cas comme ce que vous avez NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, à la place, vous devez supprimer la qualification et utiliserGUIDE_VIEW_SEVEN_DAY


Préfère celui-ci. Facile!
Lazy Ninja

5

J'aime quelques utilisations de l'énumération Java:

  1. .name () vous permet de récupérer le nom enum dans String.
  2. .ordinal () vous permet d'obtenir la valeur entière, basée sur 0.
  3. Vous pouvez attacher d'autres paramètres de valeur à chaque énumération.
  4. et, bien sûr, commutateur activé.

enum avec des paramètres de valeur:

    enum StateEnum {
        UNDEFINED_POLL  ( 1 * 1000L,       4 * 1000L),
        SUPPORT_POLL    ( 1 * 1000L,       5 * 1000L),
        FAST_POLL       ( 2 * 1000L,  4 * 60 * 1000L),
        NO_POLL         ( 1 * 1000L,       6 * 1000L); 
        ...
    }

exemple de commutateur:

private void queuePoll(StateEnum se) {
    // debug print se.name() if needed
    switch (se) {
        case UNDEFINED_POLL:
            ...
            break;
        case SUPPORT_POLL:
            ...
            break;

3

Cela devrait fonctionner de la manière que vous décrivez. Quelle erreur obtenez vous? Si vous pouviez coller votre code, cela vous aiderait.

http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

EDIT: Voulez-vous vraiment définir une énumération statique? Cela ne me semble pas juste. Une énumération ressemble beaucoup à tout autre objet. Si votre code se compile et s'exécute mais donne des résultats incorrects, ce serait probablement pourquoi.


"Les types enum imbriqués sont implicitement statiques. Il est permis de déclarer explicitement un type enum imbriqué comme étant statique." - JLS §8.9 .
trashgod

@trashgod, en effet - mais j'utiliserais toujours la déclaration implicite pour éviter toute confusion car c'est en fait plus évident IMO. Une énumération statique globale (ce que je suppose que c'est) est probablement erronée dans la plupart des cas.
SystemParadox

2
enumerations accessing is very simple in switch case

private TYPE currentView;

//declaration of enum 
public enum TYPE {
        FIRST, SECOND, THIRD
    };

//handling in switch case
switch (getCurrentView())
        {
        case FIRST:
            break;
        case SECOND:
            break;
        case THIRD:
            break;
        }

//getter and setter of the enum
public void setCurrentView(TYPE currentView) {
        this.currentView = currentView;
    }

    public TYPE getCurrentView() {
        return currentView;
    }

//usage of setting the enum 
setCurrentView(TYPE.FIRST);

avoid the accessing of TYPE.FIRST.ordinal() it is not recommended always

Cela ne fonctionne que si vous n'obtenez pas vos données en externe. Puisque OP a dit qui renvoie la valeur 1, 2, 3 pas un TYPE, votre méthode ne fonctionnerait pas sans un cas de commutateur inversé qui prend 1, 2, 3 et renvoie un TYPE avant d'entrer dans le cas de commutateur qu'il a répertorié ..
WORMSS

2

Exemple court de fonction associative:

public String getIcon(TipoNotificacao tipo)
{
    switch (tipo){
        case Comentou : return "fa fa-comments";
        case ConviteEnviou : return "icon-envelope";
        case ConviteAceitou : return "fa fa-bolt";
        default: return "";
    }
}

Comme @Dhanushka l'a dit, omettre le qualificatif à l'intérieur de "switch" est la clé.


1

Je le fais comme

public enum State
{
    // Retrieving, // the MediaRetriever is retrieving music //
    Stopped, // media player is stopped and not prepared to play
    Preparing, // media player is preparing...
    Playing, // playback active (media player ready!). (but the media player
                // may actually be
                // paused in this state if we don't have audio focus. But we
                // stay in this state
                // so that we know we have to resume playback once we get
                // focus back)
    Paused; // playback paused (media player ready!)

    //public final static State[] vals = State.values();//copy the values(), calling values() clones the array

};

public State getState()
{
        return mState;   
}

Et utiliser dans Switch Statement

switch (mService.getState())
{
case Stopped:
case Paused:

    playPause.setBackgroundResource(R.drawable.selplay);
    break;

case Preparing:
case Playing:

    playPause.setBackgroundResource(R.drawable.selpause);
    break;    
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.