Java utilizza enum con l'istruzione switch


106

Ho esaminato varie domande e risposte su SO simili a questa domanda ma non ho trovato una soluzione.

Quello che ho è un'enumerazione che rappresenta diversi modi per visualizzare una guida TV ...

Nella Applicationclasse NDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... quando l'utente cambia la vista, un gestore di eventi riceve uno int0-2 e mi piacerebbe fare qualcosa del genere ...

In un Activity onClick(DialogInterface dialog, int which)gestore di eventi Android

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

Sono abituato alle enumerazioni C # e alle istruzioni select / case che consentirebbero qualcosa di simile a quanto sopra e so che Java fa le cose in modo diverso ma non riesco a dare un senso a ciò che devo fare.

Dovrò ricorrere a ifdichiarazioni? Probabilmente ci saranno solo 3 scelte, quindi potrei farlo, ma mi chiedevo come potesse essere fatto con switch-case in Java.

EDIT Spiacente, non ho approfondito completamente il problema perché lo consideravo un problema generico di Java. Ho aggiunto alla domanda per spiegare un po 'di più.

Non c'è nulla di specifico per Android, motivo per cui non l'ho etichettato come Android ma l'enum è definito nella Applicationclasse e il codice in cui non voglio lo switch è in un file Activity. L'enumerazione è statica poiché è necessario accedervi da più attività.


1
Dovrebbe essere solo case GUIDE_VIEW_SEVEN_DAYdopo le importazioni corrette; che problema stai riscontrando?
Dave Newton

Non puoi semplicemente fare in modo che il tuo gestore di eventi riceva un'enumerazione? A parte questo, forse questo aiuterà: stackoverflow.com/questions/5292790/…
Brian Roach

@ Dave: Ops scusa, ho corretto il codice per mostrare com'è. Eclipse mi sta dando un errore di tipo non corrispondente dicendo che non può convertire da guideView a int.
Squonk

@ Brian: questa è un'app per Android e il gestore di eventi ( OnClickListener ) è definito DialogInterfacedall'interfaccia che devo implementare.
Squonk

@MisterSquonk Oh, mi mancava che lo avessi ricevuto da un int - scusa, vedi la risposta di Ophidian, anche se ho inserito la funzionalità nell'enumerazione.
Dave Newton

Risposte:


162

La parte che ti manca è la conversione dall'intero all'enumerazione indipendente dai tipi. Java non lo farà automaticamente. Ci sono un paio di modi in cui puoi farlo:

  1. Utilizza un elenco di int finali statici anziché un'enumerazione indipendente dai tipi e attiva il valore int che ricevi (questo è l'approccio pre-Java 5)
  2. Attivare un valore id specificato (come descritto da heneryville ) o il valore ordinale dei valori enum; vale a direguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Determina il valore enum rappresentato dal valore int e quindi attiva il valore 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;
        }
    }
    

    Potresti trovare più utile / meno soggetto a errori scrivere valueOfun'implementazione personalizzata che prenda i tuoi valori interi come argomento per risolvere il valore enum appropriato e ti consenta di centralizzare il controllo dei limiti.


Grazie molto. Mi ci è voluto un po 'per inserirlo nel mio codice, ma ora funziona bene con il codice di esempio che hai pubblicato. 6 anni con C # e 1 anno con Java: non capita spesso di imbattermi in qualcosa che mi lascia perplesso. Tante somiglianze ma occasionali come questa che è molto diversa. Non dimenticherò questo in fretta. :-)
Squonk

2
Hai bisogno dei nomi enum non qualificati nell'istruzione case, quindi case GuideView.SEVEN_DAY:dà un errore di compilazione, dovrebbe essere case SEVEN_DAY:.
haridsv

È superbo fratello !!
Neo

42

Se whichViewè un oggetto di GuideView Enum, seguire funziona bene. Si noti che non esiste un qualificatore per la costante dopo case.

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

4
come è possibile ?!
Jes Chergui

12

Le enumerazioni non dovrebbero essere qualificate all'interno dell'etichetta del caso come quello che hai NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, invece dovresti rimuovere la qualificazione e l'usoGUIDE_VIEW_SEVEN_DAY


Preferisce questo. Semplice!
Lazy Ninja

5

Mi piacciono alcuni usi di Java enum:

  1. .name () ti consente di recuperare il nome dell'enumerazione in String.
  2. .ordinal () ti consente di ottenere il valore intero, basato su 0.
  3. È possibile allegare altri parametri di valore con ogni enumerazione.
  4. e, naturalmente, interruttore abilitato.

enum con parametri di valore:

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

esempio di interruttore:

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

3

Questo dovrebbe funzionare nel modo in cui descrivi. Che errore stai ricevendo? Se potessi incollare il tuo codice questo sarebbe d'aiuto.

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

EDIT: Sei sicuro di voler definire un'enumerazione statica? Non mi suona bene. Un enum è molto simile a qualsiasi altro oggetto. Se il codice viene compilato ed eseguito ma fornisce risultati errati, probabilmente questo sarebbe il motivo.


"I tipi enum annidati sono implicitamente statici. È consentito dichiarare esplicitamente statico un tipo enum annidato." - JLS §8.9 .
trashgod

@trashgod, infatti- ma userei sempre la dichiarazione implicita per evitare confusione in quanto in realtà è più ovvio IMO. Un'enumerazione statica globale (che è ciò che presumo sia) probabilmente è sbagliata nella maggior parte dei casi.
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

Funziona solo se non ricevi i tuoi dati esternamente. Poiché OP ha detto che restituisce il valore 1, 2, 3 non è un TIPO, il tuo metodo non funzionerebbe senza un caso di interruttore invertito che prende 1, 2, 3 e restituisce un TIPO prima di entrare nel caso di interruttore che ha elencato ..
WORMSS

2

Breve esempio di funzione associativa:

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

Come ha detto @Dhanushka, omettere il qualificatore all'interno di "switch" è la chiave.


1

Lo sto facendo così

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

E usalo nell'istruzione Switch

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

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

case Preparing:
case Playing:

    playPause.setBackgroundResource(R.drawable.selpause);
    break;    
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.