Ao trabalhar com variáveis / parâmetros que podem assumir apenas um número finito de valores, tento sempre usar Java enum
, como em
public enum BonusType {
MONTHLY, YEARLY, ONE_OFF
}
Contanto que eu permaneça dentro do meu código, funciona bem. No entanto, geralmente preciso fazer a interface com outro código que usa valores simples int
(ou String
) para o mesmo propósito, ou preciso ler / gravar de / para um banco de dados onde os dados são armazenados como um número ou string.
Nesse caso, gostaria de ter uma maneira conveniente de associar cada valor de enum a um inteiro, de modo que eu possa converter as duas formas (em outras palavras, preciso de um "enum reversível").
Ir de enum para int é fácil:
public enum BonusType {
public final int id;
BonusType(int id) {
this.id = id;
}
MONTHLY(1), YEARLY(2), ONE_OFF(3);
}
Então, posso acessar o valor int como BonusType x = MONTHLY; int id = x.id;
.
No entanto, não consigo ver nenhuma maneira agradável de fazer o contrário, ou seja, indo de int para enum. Idealmente, algo como
BonusType bt = BonusType.getById(2);
As únicas soluções que consegui encontrar são:
- Coloque um método de pesquisa no enum, que usa
BonusType.values()
para preencher um mapa "int -> enum", então armazena isso em cache e o usa para pesquisas. Funcionaria, mas eu teria que copiar esse método de forma idêntica em cada enum que eu usar :-(. - Coloque o método de pesquisa em uma classe de utilitário estático. Então, eu precisaria apenas de um método de "pesquisa", mas teria que mexer com a reflexão para fazê-lo funcionar para um enum arbitrário.
Ambos os métodos parecem terrivelmente estranhos para um problema tão simples (?).
Alguma outra ideia / percepção?
fonte
ordinal()
.ordinal()
são decididos por você (ou seja, você não poderia simplesmente usar ) ou são decididos por forças externas?Respostas:
http://www.javaspecialists.co.za/archive/Issue113.html
A solução começa semelhante à sua, com um valor int como parte da definição de enum. Ele então cria um utilitário de pesquisa baseado em genéricos:
Esta solução é boa e não requer 'mexer na reflexão' porque é baseada no fato de que todos os tipos de enum herdam implicitamente a interface Enum.
fonte
Number
vez deByte
, porque meu valor de apoio pode ser maior em tamanho.enum → int
int → enum
String → enum
enum → String
Uma observação lateral:
como você assinalou corretamente, o
ordinal()
pode ser "instável" de versão para versão. Esta é a razão exata pela qual sempre armazeno constantes como strings em meus bancos de dados. (Na verdade, ao usar o MySql, eu os armazeno como enums do MySql !)fonte
BonusType.valueOf("MONTHLY")
)ordinal()
me parece uma solução problemática, porque vai quebrar quando a lista de valores enum for reorganizada ou um valor for excluído. Além disso, isso só é prático se os valores int forem 0 ... n (o que muitas vezes descobri não ser o caso).values()
matriz só funcionará se todos os seus valores forem 0 indexados para seus ids e declarados em ordem. (Eu testei isso para verificar se você declaraFOO(0), BAR(2), BAZ(1);
issovalues[1] == BAR
evalues[2] == BAZ
apesar dos ids terem passado.)double
).Achei isso na web, foi muito útil e simples de implementar. Esta solução NÃO foi feita por mim
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
}
fonte
Parece que a (s) resposta (s) a esta pergunta estão desatualizadas com o lançamento do Java 8.
fonte
Collectors.toMap()
ser emFunctions.identity()
vez denull
?org.apache.commons.lang.enums.ValuedEnum;
Para me poupar escrevendo um monte de código clichê ou duplicando código para cada Enum, usei o Apache Commons Lang
ValuedEnum
.Definição :
Uso:
int -> ValuedEnum:
fonte
Você poderia talvez usar algo como
Isso reduziria a necessidade de reflexão em sua classe de utilitários.
fonte
Neste código, para busca permanente e intensa, tenho memória ou processo para uso, e seleciono memória, com array conversor como índice. Espero que seja útil
fonte
Use uma interface para mostrar quem é o chefe.
E o resultado:
fonte
Ambos os
.ordinal()
evalues()[i]
são instáveis, pois são dependentes da ordem dos enums. Portanto, se você alterar a ordem dos enums ou adicionar / deletar alguns, o programa será interrompido.Aqui está um método simples, mas eficaz, para mapear entre enum e int.
Aplicá-lo para strings não deve ser difícil.
fonte
Etapa 1 Definir um
interface
EnumConverterPasso 2
Crie um nome de classe ReverseEnumMap
etapa 3
Vá até sua
Enum
classe e,implement
éEnumConverter<ContentType>
claro, substitua os métodos de interface. Você também precisa inicializar um ReverseEnumMap estático.Passo 4
Agora crie um
Communication
arquivo de classe e chame seu novo método para converter umEnum
paraString
eString
paraEnum
. Acabei de colocar o método principal para fins de explicação.Clique para obter uma explicação completa
fonte
ContentType convert(String pKey)
estática, o que tira a necessidade daCommunication
aula e ficou mais do meu agrado. +1Não tenho certeza se é o mesmo em Java, mas os tipos de enum em C também são mapeados automaticamente para inteiros, portanto, você pode usar o tipo ou o inteiro para acessá-lo. Você já tentou acessá-lo simplesmente com um número inteiro?
fonte
.ordinal()
método. (Da outra maneira, useBonusType.values()[i]
.) Mas no exemplo citado acima, os índices aqui e os valores externos não coincidem.Ótima pergunta :-) Eu usei uma solução parecida com a do Sr. Ferguson há algum tempo. Nosso enum descompilado é assim:
Vendo isso é evidente porque
ordinal()
é instável. É oi
dentrosuper(s, i);
. Também estou pessimista de que você possa pensar em uma solução mais elegante do que essas que você já enumerou. Afinal, enums são classes como quaisquer classes finais.fonte
Para fins de integridade, aqui está uma abordagem genérica para recuperar valores enum por índice de qualquer tipo de enum. Minha intenção era fazer com que o método se parecesse com Enum.valueOf (Class, String) . Fyi, copiei este método daqui .
Questões relacionadas ao índice (já discutidas em detalhes aqui) ainda se aplicam.
fonte
MyEnumType.values()
- sem necessidade de um método auxiliar estático.fonte
Eu precisava de algo diferente porque queria usar uma abordagem genérica. Estou lendo o enum de e para matrizes de bytes. É aqui que eu penso:
Exemplo de enum:
}
fonte
Só porque a resposta aceita não é independente:
Código de suporte:
Exemplo de uso:
fonte
dado:
public enum BonusType {MONTHLY (0), YEARLY (1), ONE_OFF (2)}
BonusType bonus = YEARLY;
System.out.println (bonus.Ordinal () + ":" + bônus)
Produto: 1: ANO
fonte
Se você tem um carro de classe
E a propriedade Color é uma classe
E você deseja converter Color para um Enum
Basta adicionar um método na classe Color para converter Color em ColorEnum
e dentro de ColorEnum implementa o método getById ()
Agora você pode usar um classMap
fonte