Java usando enum con declaración de cambio


106

He mirado varias preguntas y respuestas sobre SO similares a esta pregunta pero no he encontrado una solución.

Lo que tengo es una enumeración que representa diferentes formas de ver una guía de TV ...

En la Applicationclase NDroid

static enum guideView {
    GUIDE_VIEW_SEVEN_DAY,
    GUIDE_VIEW_NOW_SHOWING,
    GUIDE_VIEW_ALL_TIMESLOTS
}

... cuando el usuario cambia la vista, un controlador de eventos recibe un int0-2 y me gustaría hacer algo como esto ...

En un Activity onClick(DialogInterface dialog, int which)controlador de eventos de Android

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

Estoy acostumbrado a las enumeraciones de C # y las declaraciones select / case que permitirían algo como lo anterior y sé que Java hace las cosas de manera diferente, pero no puedo entender lo que tengo que hacer.

¿Voy a tener que recurrir a ifdeclaraciones? Es probable que solo haya 3 opciones, por lo que podría hacerlo, pero me preguntaba cómo se podría hacer con switch-case en Java.

EDITAR Lo siento, no amplié completamente el problema ya que lo veía como un problema genérico de Java. Agregué a la pregunta para explicar un poco más.

No hay nada que sea específico de Android, por lo que no lo etiqueté como Android, pero la enumeración está definida en la Applicationclase y el código donde no quiero que el interruptor esté en un Activity. La enumeración es estática ya que necesito acceder a ella desde múltiples actividades.


1
Debería ser solo case GUIDE_VIEW_SEVEN_DAYdespués de las importaciones adecuadas; ¿Qué problema (s) tienes?
Dave Newton

¿No puedes hacer que tu controlador de eventos reciba una enumeración? Aparte de eso, tal vez esto ayude: stackoverflow.com/questions/5292790/…
Brian Roach

@Dave: Vaya, lo siento, he corregido el código para mostrar cómo es. Eclipse me está dando un error de tipo no coincidente que dice que no se puede convertir de guideView a int.
Squonk

@Brian: esta es una aplicación de Android y el controlador de eventos ( OnClickListener ) está definido por la DialogInterfaceinterfaz que tengo que implementar.
Squonk

@MisterSquonk Oh, extrañé que lo recibieras de un int - lo siento, mira la respuesta de Ophidian, aunque pondría la funcionalidad en la enumeración.
Dave Newton

Respuestas:


162

La parte que te falta es la conversión del número entero a la enumeración de tipo seguro. Java no lo hará automáticamente. Hay un par de formas en las que puede hacer esto:

  1. Use una lista de entradas finales estáticas en lugar de una enumeración segura de tipos y active el valor int que recibe (este es el enfoque anterior a Java 5)
  2. Active un valor de identificación especificado (como lo describe heneryville ) o el valor ordinal de los valores de enumeración; es decirguideView.GUIDE_VIEW_SEVEN_DAY.ordinal()
  3. Determine el valor de enumeración representado por el valor int y luego active el valor de enumeración.

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

    Puede que le resulte más útil / menos propenso a errores escribir una valueOfimplementación personalizada que tome sus valores enteros como argumento para resolver el valor de enumeración apropiado y le permita centralizar la verificación de límites.


Muchas gracias. Me tomó un tiempo incorporarlo a mi código, pero ahora está funcionando bien con el código de ejemplo que publicaste. 6 años con C # y 1 año con Java; no es frecuente que me encuentre con algo que me desconcierte. Tantas similitudes, pero una ocasional como esta, que es muy diferente. No olvidaré este de prisa. :-)
Squonk

2
Necesita los nombres de enumeración no calificados en la declaración del caso, por lo que case GuideView.SEVEN_DAY:da un error de compilación, debería ser case SEVEN_DAY:.
haridsv

¡Es magnífico hermano!
Neo

42

Si whichViewes un objeto de GuideView Enum, lo siguiente funciona bien. Tenga en cuenta que no hay ningún calificador para la constante posterior case.

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

4
¡¿Como es esto posible?!
Jes Chergui

12

Las enumeraciones no deben estar calificadas dentro de la etiqueta del caso como lo que tiene NDroid.guideView.GUIDE_VIEW_SEVEN_DAY, en su lugar, debe eliminar la calificación y usarGUIDE_VIEW_SEVEN_DAY


Prefiere este. ¡Sencillo!
Lazy Ninja

5

Me gustan algunos usos de la enumeración de Java:

  1. .name () le permite buscar el nombre de enumeración en String.
  2. .ordinal () le permite obtener el valor entero, basado en 0.
  3. Puede adjuntar otros parámetros de valor con cada enumeración.
  4. y, por supuesto, interruptor habilitado.

enumeración con parámetros de valor:

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

ejemplo de interruptor:

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

3

Esto debería funcionar de la forma que usted describe. ¿Qué error estás recibiendo? Si pudiera pegar su código, eso ayudaría.

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

EDITAR: ¿Estás seguro de que quieres definir una enumeración estática? Eso no me suena bien. Una enumeración es muy parecida a cualquier otro objeto. Si su código se compila y se ejecuta pero da resultados incorrectos, probablemente esta sea la razón.


"Los tipos de enumeración anidados son implícitamente estáticos. Está permitido declarar explícitamente que un tipo de enumeración anidado es estático". - JLS §8.9 .
trashgod

@trashgod, de hecho, pero siempre usaría la declaración implícita para evitar confusiones, ya que en realidad es más obvio en mi opinión. Una enumeración estática global (que es lo que supongo que es) probablemente sea incorrecta en la mayoría de los casos.
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

Eso solo funciona si no obtiene sus datos de forma externa. Dado que OP dijo que devuelve el valor 1, 2, 3 no es un TIPO, su método no funcionaría sin un caso de interruptor invertido que toma 1, 2, 3 y devuelve un TIPO antes de entrar en el caso de interruptor que enumeró ..
WORMSS

2

Ejemplo breve de función asociativa:

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

Como dijo @Dhanushka, omitir el calificador dentro de "switch" es la clave.


1

Lo estoy haciendo como

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

Y usar en 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;    
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.