Java przy użyciu enum z instrukcją switch

106

Spojrzałem na różne pytania i odpowiedzi na SO podobne do tego pytania, ale nie znalazłem rozwiązania.

To, co mam, to wyliczenie, które reprezentuje różne sposoby przeglądania przewodnika telewizyjnego ...

W Applicationklasie NDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... kiedy użytkownik zmienia widok, program obsługi zdarzeń otrzymuje intod 0-2 i chciałbym zrobić coś takiego ...

W programie Activity onClick(DialogInterface dialog, int which)obsługi zdarzeń systemu Android

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

Jestem przyzwyczajony do wyliczeń C # i instrukcji select / case, które pozwoliłyby na coś takiego jak powyższe i wiem, że Java robi rzeczy inaczej, ale po prostu nie mogę zrozumieć, co muszę zrobić.

Czy będę musiał uciekać się do ifoświadczeń? Prawdopodobnie będą tylko 3 opcje, więc mogłem to zrobić, ale zastanawiałem się, jak można to zrobić z przełącznikiem w Javie.

EDYTUJ Przepraszamy, nie rozwinęłam tego problemu całkowicie, ponieważ patrzyłem na niego jako na ogólny problem z Javą. Dodałem do pytania, aby nieco bardziej wyjaśnić.

Nie ma niczego, co jest specyficzne dla Androida, dlatego nie oznaczyłem go jako Androida, ale wyliczenie jest zdefiniowane w Applicationklasie, a kod, w którym nie chcę, aby przełącznik znajdował się w pliku Activity. Wyliczenie jest statyczne, ponieważ muszę uzyskać do niego dostęp z wielu działań.

Squonk
źródło
1
Powinien być case GUIDE_VIEW_SEVEN_DAYpo odpowiednim imporcie; jaki masz problem (y)?
Dave Newton
Czy nie możesz po prostu sprawić, aby program obsługi zdarzeń otrzymał wyliczenie? Poza tym, być może to pomoże: stackoverflow.com/questions/5292790/…
Brian Roach
@Dave: Ups, przepraszam, poprawiłem kod, żeby pokazać, jak to jest. Eclipse daje mi błąd niezgodności typu, mówiąc, że nie można przekonwertować z guideView na int.
Squonk
@Brian: To jest aplikacja na Androida, a program obsługi zdarzeń ( OnClickListener ) jest zdefiniowany przez DialogInterfaceinterfejs, który muszę zaimplementować.
Squonk
@MisterSquonk Och, tęskniłem za tym, że dostałeś to z int - przepraszam, zobacz odpowiedź Ophidian, chociaż umieściłem funkcjonalność w wyliczeniu.
Dave Newton

Odpowiedzi:

162

Brakująca część to konwersja z liczby całkowitej do wyliczenia bezpiecznego dla typu. Java nie zrobi tego automatycznie. Można to zrobić na kilka sposobów:

  1. Użyj listy statycznych końcowych liczb całkowitych zamiast wyliczenia bezpiecznego dla typów i włącz otrzymaną wartość int (jest to podejście sprzed Java 5)
  2. Włącz określoną wartość identyfikatora ( opisaną przez Heneryville ) lub wartość porządkową wartości wyliczonych ; to znaczyguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Określ wartość wyliczenia reprezentowaną przez wartość int, a następnie włącz wartość wyliczenia.

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

    Może się okazać, że bardziej pomocne / mniej podatne na błędy będzie napisanie niestandardowej valueOfimplementacji, która przyjmuje wartości całkowite jako argument w celu rozwiązania odpowiedniej wartości wyliczenia i umożliwia scentralizowanie sprawdzania granic.

Ofidian
źródło
Wielkie dzięki. Zajęło mi trochę czasu, zanim wprowadziłem go do mojego kodu, ale teraz działa dobrze z przykładowym kodem, który opublikowałeś. 6 lat z C # i 1 rok z Javą - nieczęsto trafiam na coś, co mnie przytłacza. Tyle podobieństw, ale sporadyczne takie jak ten, które są tak bardzo różne. Nie zapomnę tego w pośpiechu. :-)
Squonk
2
Potrzebujesz niekwalifikowanych nazw wyliczeń w instrukcji case, więc case GuideView.SEVEN_DAY:daje błąd kompilacji, a powinien case SEVEN_DAY:.
haridsv
To wspaniały stary!
Neo
42

Jeśli whichViewjest obiektem GuideView Enum, następujące działa dobrze. Należy pamiętać, że nie ma kwalifikatora dla stałej po case.

switch (whichView) {
    case SEVEN_DAY:
        ...
        break;
    case NOW_SHOWING:
        ...
        break;
}
Dhanushka
źródło
4
Jak to w ogóle jest możliwe?!
Jes Chergui
12

Wyliczenia nie powinny być kwalifikowane w etykiecie przypadku, tak jak to, co masz NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, zamiast tego należy usunąć kwalifikację i użyćGUIDE_VIEW_SEVEN_DAY

Piyush Mattoo
źródło
Woli ten. Prosty!
Lazy Ninja
5

Podoba mi się kilka zastosowań wyliczenia w Javie:

  1. .name () umożliwia pobranie nazwy wyliczenia w ciągu znaków.
  2. .ordinal () pozwala uzyskać wartość całkowitą, zaczynającą się od 0.
  3. Do każdego wyliczenia można dołączyć inne parametry wartości.
  4. i, oczywiście, przełącznik włączony.

wyliczenie z parametrami wartości:

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

przykład przełącznika:

private void queuePoll(StateEnum se) {
    // debug print se.name() if needed
    switch (se) {
        case UNDEFINED_POLL:
            ...
            break;
        case SUPPORT_POLL:
            ...
            break;
david m lee
źródło
3

Powinno to działać w sposób, który opisujesz. Jaki błąd otrzymujesz? Gdybyś mógł wkleić swój kod, to by pomogło.

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

EDYCJA: Czy na pewno chcesz zdefiniować statyczne wyliczenie? To nie brzmi dla mnie dobrze. Wyliczenie jest podobne do każdego innego obiektu. Jeśli twój kod kompiluje się i działa, ale daje nieprawidłowe wyniki, prawdopodobnie jest to przyczyna.

SystemParadox
źródło
„Zagnieżdżone typy wyliczeniowe są niejawnie statyczne. Dopuszczalne jest jawne zadeklarowanie zagnieżdżonego typu wyliczenia jako statycznego.” - JLS §8.9 .
trashgod
@trashgod, rzeczywiście - ale zawsze używałbym domyślnej deklaracji, aby uniknąć nieporozumień, ponieważ jest to bardziej oczywiste IMO. Globalne statyczne wyliczenie (które zakładam, że to jest) jest prawdopodobnie w większości przypadków błędne.
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
Jaya
źródło
Działa to tylko wtedy, gdy nie otrzymujesz danych z zewnątrz. Ponieważ OP powiedział, że zwraca wartość 1, 2, 3, a nie TYP, twoja metoda nie działałaby bez odwróconego przypadku przełącznika, który przyjmuje 1, 2, 3 i zwraca TYP przed przejściem do wymienionego przypadku przełącznika ..
WORMSS
2

Krótki przykład funkcji asocjacyjnej:

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

Jak powiedział @Dhanushka, pomiń kwalifikator w kluczu „przełącznik”.

Auston
źródło
1

Robię to jak

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

I użyj w instrukcji Switch

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

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

case Preparing:
case Playing:

    playPause.setBackgroundResource(R.drawable.selpause);
    break;    
}
AndroidGeek
źródło