Java, використовуючи enum з оператором switch


106

Я розглянув різні питання та відповіді на подібне до цього питання, але не знайшов рішення.

У мене є перерахунок, який представляє різні способи перегляду телевізійного довідника ...

У Applicationкласі NDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... коли користувач змінює подання, обробник події отримує значення int0-2, і я хотів би зробити щось подібне ...

У обробці Activity onClick(DialogInterface dialog, int which)подій для Android

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

Я звик до переліків на C # та вибору / випадок, що дозволяв би щось подібне, і я знаю, що Java робить інакше, але я просто не можу зрозуміти, що мені потрібно робити.

Чи доведеться вдаватися до ifзаяв? Можливо, колись буде лише 3 варіанти, тому я міг би це зробити, але мені цікаво, як це можна зробити з корпусом перемикача на Java.

EDIT Вибачте, я не розширив цю проблему повністю, тому що я розглядав її як загальну проблему Java. Я додав до питання, щоб пояснити трохи далі.

Немає нічого, що є специфічним для Android, і тому я не позначив його як Android, але перелік визначається в Applicationкласі, і код, у якому я не хочу перемикання, знаходиться в Activity. Перелік є статичним, оскільки мені потрібно отримати доступ до нього з декількох видів діяльності.


1
Потрібно просто case GUIDE_VIEW_SEVEN_DAYпісля належного імпорту; які проблеми у вас є?
Дейв Ньютон

Ви не можете просто змусити обробника подій отримати суму? Окрім цього, можливо, це допоможе: stackoverflow.com/questions/5292790/…
Брайан Роуч

@Dave: На жаль, я виправив код, щоб показати, як це. Eclipse дає мені помилку невідповідності типу, кажучи, що вона не може перетворити з guideView в int.
Сквонк

@Brian: Це додаток для Android, і обробник подій ( OnClickListener ) визначається DialogInterfaceінтерфейсом, який я маю реалізувати.
Скуонк

@MisterSquonk О, я сумую за тим, що ви отримували це з int - вибачте, дивіться відповідь Офідіана, хоча я вклав функціонал у перерахунок.
Дейв Ньютон

Відповіді:


162

Частина, яка вам не вистачає, перетворюється з цілого числа в перелік, що захищає тип. Java не зробить це автоматично. Є кілька способів вирішити це:

  1. Скористайтеся списком статичних кінцевих вводів, а не безпечним переліком переліку та увімкніть отримане значення int (це попередній підхід до Java 5)
  2. Увімкніть або задане значення id (як описано heneryville ), або порядкове значення значень enum; тобтоguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Визначте значення enum, представлене значенням int, а потім увімкніть значення 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;
        }
    }

    Вам може бути кориснішим / менш схильним до помилок написання власної valueOfреалізації, яка приймає ваші цілі значення як аргумент для вирішення відповідного значення перерахунку та дозволяє централізувати перевірку своїх меж.


Велике дякую. Мені знадобилося деякий час, щоб я вніс це в свій код, але він зараз добре працює з прикладом коду, який ви опублікували. 6 років з C # і 1 рік з Java - не часто я натрапляю на щось, що мене спотикає. Стільки подібностей, але випадкові подібні, як це дуже різні. Я не забуду цього поспіхом. :-)
Скуонк

2
Вам потрібні некваліфіковані імена enum у викладі справи, тому case GuideView.SEVEN_DAY:дає помилку компіляції, вона повинна бути case SEVEN_DAY:.
haridsv

Це чудовий брато !!
Нео

42

Якщо whichViewє об'єктом GuideView Enum, наступне працює добре. Зауважте, що для постійних після не існує кваліфікатора case.

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

4
як це можливо навіть ?!
Jes Chergui

12

Перерахунки не повинні бути кваліфіковані у випадку, як те, що у вас є NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, натомість слід видалити кваліфікацію та використовуватиGUIDE_VIEW_SEVEN_DAY


Віддає перевагу цьому. Просто!
Ледачий Ніндзя

5

Мені подобається кілька звичок Java enum:

  1. .name () дозволяє отримати ім'я enum у String.
  2. .ordinal () дозволяє отримати ціле значення, засноване на 0.
  3. Ви можете приєднати інші параметри значень до кожного перерахунку.
  4. і, звичайно, перемикач увімкнено.

перерахунок із значеннями параметрів:

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

Приклад перемикача:

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

3

Це має працювати так, як ви описуєте. Яку помилку ви отримуєте? Якщо ви можете вставити код, це допоможе.

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

EDIT: Ви впевнені, що хочете визначити статичний перелік? Це мені не здається правильним. Перерахунок схожий на будь-який інший об’єкт. Якщо ваш код збирається та працює, але дає неправильні результати, це, мабуть, саме тому.


"Вкладені типи перерахунків неявно статичні. Дозволено явно оголосити вкладений тип перерахунку статичним". - JLS §8.9 .
trashgod

@trashgod, справді - але я завжди використовував неявну декларацію, щоб уникнути плутанини, оскільки це насправді більш очевидний ІМО. Глобальний статичний перелік (який я припускаю, що це таке), ймовірно, у більшості випадків помиляється.
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

Це працює лише в тому випадку, якщо ви не отримуєте свої дані зовні. Оскільки ОП сказав, що повертає значення 1, 2, 3, а не ТИП, ваш метод не працюватиме без зворотного корпусу комутатора, який займає 1, 2, 3 і повертає ТИП перед тим, як перейти до справи перемикача, який він перерахував ..
WORMSS

2

Короткий приклад асоціативної функції:

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

Як сказав @Dhanushka, пропустити класифікатор всередині "перемикач" є ключем.


1

Я роблю це так

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

І використовувати в програмі Switch

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

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

case Preparing:
case Playing:

    playPause.setBackgroundResource(R.drawable.selpause);
    break;    
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.