32 votos

¿Java valueOf() enum con valores múltiples?

Tengo un problema en Java uso de las Enumeraciones. He leído la documentación sobre la asignación de los parámetros de valor para las Enumeraciones. Pero, mi pregunta es, ¿qué acerca de varios valores, es posible?

Esto es lo que me gustaría conseguir: Tengo un Enum para las lenguas. Cada idioma es representado por su nombre y algunos más corto alias (no siempre, y no siempre el mismo número de alias)

He aquí un ejemplo:

public enum Language{
English("english", "eng", "en", "en_GB", "en_US"),
German("german", "de", "ge"),
Croatian("croatian", "hr", "cro"),
Russian("russian")
}

¿Sólo se puede definir una Enumeración como este y de obtener el derecho de los valores enum llamando Idioma.valueOf() ???

49voto

Flavio Puntos 5369

Esto es probablemente similar a lo que usted está tratando de lograr.

public enum Language{
    English("english", "eng", "en", "en_GB", "en_US"),
    German("german", "de", "ge"),
    Croatian("croatian", "hr", "cro"),
    Russian("russian");

    private final List<String> values;

    Language(String ...values) {
        this.values = Arrays.asList(values);
    }

    public List<String> getValues() {
        return values;
    }
}

Recuerde que las enumeraciones son una clase como los demás; English("english", "eng", "en", "en_GB", "en_US")llama al constructor del enum.

Luego pudo recuperar el valor de la enumeración correspondiente a una cadena a través de un método de búsqueda (se puede poner como un método estático en la enumeración otra vez).

public static Language find(String name) {
    for (Language lang : Language.values()) {
        if (lang.getValues().contains(name)) {
            return lang;
        }
    }
    return null;
}

8voto

JoD. Puntos 188

La asignación de una cadena a un valor de enumeración, es por lo general lo que el valueOf método estático está haciendo para usted. Así que si quieres formar este con el uso de sinónimos, usted tendrá que desarrollar algo similar. Sin embargo, no queremos dar la posibilidad de que podemos sobreescribir un método estático, por lo que sólo un nombre diferente para este propósito: fromString debe ser la adecuada.

public enum Language { 
  ENGLISH("eng", "en", "en_GB", "en_US"),   
  GERMAN("de", "ge"),   
  CROATIAN("hr", "cro"),   
  RUSSIAN("ru"),
  BELGIAN("be",";-)");

  static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>(); 
  static { 
    for (Command type:Command.values()) { 
      // ignoring the case by normalizing to uppercase
      ALIAS_MAP.put(type.getKey().toUpper(),type); 
      for (String alias:type.aliases) ALIAS_MAP.put(alias.toUpper(),type); 
    } 
  } 

  static public boolean has(String value) { 
    // ignoring the case by normalizing to uppercase
    return ALIAS_MAP.containsKey(value.toUpper()); 
  } 

  static public Language fromString(String value) { 
    if (value == null) throw new NullPointerException("alias null"); 
    Command command = ALIAS_MAP.get(value); 
    if (command == null) throw new IllegalArgumentException("Not an alias: "+value); 
    return command; 
  } 

  private List<String> aliases; 
  private Language(String... aliases) { 
    this.aliases = Arrays.asList(aliases); 
  } 
} 

Como un beneficio de este tipo de aplicación nos puede, como se ha demostrado, también implementar fácilmente la has método estático para probar si una determinada alias es parte de la enumeración valor establecido. Al mismo tiempo, hemos aplicado algunas buenas convenciones de nomenclatura:

  • la enumeración de los valores de ir en mayúsculas, para indicar que son en realidad estática final (singleton casos).
  • al mismo tiempo, también nos coloca todos los otros static final todo en mayúsculas.

Tenga en cuenta que no tenemos que repetir el nombre de la enumeración valor en sí mismo: siempre nos considder su propio nombre automáticamente (se añade a la ALIAS_MAP), y en la parte superior podemos normalizar todo a mayúsculas para hacerla insensible a mayúsculas-minúsculas.

Parece grande, pero mientras que el uso de la enumeración, se ve prety:

public void main() {
  Language myLanguage = Language.fromString("en_GB");
  if (myLanguage == Language.ENGLISH) {
    System.out.println("Yes, I know, you understand English!");
  }
} 

Ahora, la razón por la que estamos utilizando ALIAS_MAP es porque nos intuitivily entender que para un óptimo valueOf búsqueda de los valores de enumeración es necesario hacer una copia de alguna manera con un Mapa ya. Sin embargo, no tenemos acceso a ella, por lo que terminan replicando por nuestra propia cuenta. El Mapa, en realidad actúa como un índice para ofrecer una fácil búsqueda. Podríamos haber utilizado otras propiedades que el nombre de índice de búsqueda. En realidad, en este caso podemos utilizar otras propiedades: el alias que nos almacén por valor. Podemos utilizar el alias de cada valor de enumeración para construir el mundial (estática) índice.

En este punto en el tiempo, no puedo confirmar si esto es cierto que el valueOf está respaldado por un Mapa, pero todos podemos imaginar fácilmente. De cualquier manera, las enumeraciones abiertas a una gran cantidad de tiempo de compilación de optimización, por lo que el valueOf podría ser reemplazado en línea con algo totalmente diferente. Tal vez esa es la razón por la que el Mapa no es ni siquiera expuestos.

3voto

Andy Pryor Puntos 4118

En corto, no.

El parámetro para el método valueOf() debe ser sólo la cadena del tipo enum constante. Así que no puede variar, o buscar valores posibles. Consulte el JavaDoc.

Necesita escribir su propio método de utilidad para devolver el tipo enum apropiado para los valores dados.

2voto

EJP Puntos 113412

Normalizar los datos:

public enum LanguageCode
{
  ENGLISH,
  GERMAN,
  CROATIAN,
  RUSSIAN,
  // ...
}
// (add whatever initialization you want to that

Entonces

public enum Language{
  english(ENGLISH),
  eng(ENGLISH),
  en(ENGLISH),
  en_GB(ENGLISH),
  // ...
}

etc.

2voto

AlexR Puntos 60796

Yo te recomiendo ver mis artículos: http://java.dzone.com/articles/enum-tricks-customized-valueof y http://java.dzone.com/articles/enum-tricks-hierarchical-data

Aunque no estoy seguro de entender exactamente qué usted quiere realmente creo que al menos uno de estos artículos contienen la respuesta a su pregunta.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X