Eu estou muito familiarizado com o C #, mas começando a trabalhar mais em Java. Eu esperava aprender que as enums em Java eram basicamente equivalentes às do C #, mas aparentemente esse não é o caso. Inicialmente, fiquei empolgado ao saber que as enumerações Java podiam conter vários dados, o que parece muito vantajoso ( http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ). No entanto, desde então, encontrei muitos recursos ausentes que são triviais em C #, como a capacidade de atribuir facilmente um elemento de enum a um determinado valor e, consequentemente, a capacidade de converter um número inteiro em enum sem uma quantidade razoável de esforço ( ie Converter valor inteiro para Java Enum correspondente ).
Então, minha pergunta é a seguinte: existe algum benefício para as enumerações de Java sobre uma classe com vários campos finais estáticos públicos? Ou apenas fornece uma sintaxe mais compacta?
EDIT: Deixe-me ser mais claro. Qual é o benefício das enumerações Java sobre uma classe com vários campos finais estáticos públicos do mesmo tipo ? Por exemplo, no exemplo de planetas no primeiro link, qual é a vantagem de um enum sobre uma classe com essas constantes públicas:
public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
Tanto quanto posso dizer, a resposta de casablanca é a única que satisfaz isso.
public static final
campos, que podem ser valores digitados e não necessariamenteint
s.S
, então agora estamos falando de provavelmente passá-los para funções, etc. Precisamos de segurança de tipo? Bem, não, mas a maioria das pessoas considera os tipos c de estilo "tudo é umvoid*
" bom e isso pode impedir bugs (especialmente se você passar mais de um parâmetro enum / string!). Além disso, coloca as constantes em seu próprio espaço para nome, etc. Ao contrário disso, não há vantagem real em ter apenas variáveis simples.int
s, não existe um tipo de segurança, pois é possível transmitir qualquer valor. Os objetos digitados, por outro lado, não são diferentes das enumerações em termos de segurança de tipo.Respostas:
Tecnicamente, pode-se ver enum como uma classe com um monte de constantes digitadas, e é assim que as constantes enum são implementadas internamente. O uso de um
enum
no entanto fornece métodos úteis ( Enum javadoc ) que você teria que implementar de outra maneira, comoEnum.valueOf
.fonte
.values()
necessário percorrer a lista de valores.switch
declaraçãocase
declaração sem qualificação.ordinal().
EnumSet
eEnumMap
aulas.fonte
switch
declarações que foram a motivação original para o uso de umaEnum
.Ninguém mencionou a capacidade de usá-los em
switch
declarações; Vou jogar isso também.Isso permite que enumerações arbitrariamente complexas sejam usadas de maneira limpa, sem o uso de sequências
instanceof
potencialmente confusasif
ou valores de comutação sem string / int. O exemplo canônico é uma máquina de estado.fonte
A principal vantagem é a segurança do tipo. Com um conjunto de constantes, qualquer valor do mesmo tipo intrínseco pode ser usado, introduzindo erros. Com uma enumeração, apenas os valores aplicáveis podem ser usados.
Por exemplo
vs
fonte
setSize(null)
seu segundo exemplo, mas é provável que falhe muito antes do erro do primeiro exemplo.Há menos confusão. Tome
Font
por exemplo. Ele possui um construtor que leva o nome do queFont
você deseja, seu tamanho e estilo (new Font(String, int, int)
). Até hoje não me lembro se o estilo ou o tamanho vão primeiro. SeFont
tivesse usado umenum
para todos os seus diferentes estilos (PLAIN
,BOLD
,ITALIC
,BOLD_ITALIC
), seu construtor seria semelhanteFont(String, Style, int)
, evitando qualquer confusão. Infelizmente,enum
não existiam quando oFont
existia classe foi criada e, como o Java precisa manter a compatibilidade reversa, sempre seremos afetados por essa ambiguidade.Obviamente, este é apenas um argumento para usar constantes em
enum
vez depublic static final
constantes. As enums também são perfeitas para singletons e implementam o comportamento padrão, permitindo uma personalização posterior (ou seja, o padrão de estratégia ). Um exemplo do último éjava.nio.file
'sOpenOption
eStandardOpenOption
: se um desenvolvedor quisesse criar seu próprio não-padrãoOpenOption
, ele poderia.fonte
enum
sem usar varargs ou aSet
para pegar um número arbitrário deles.interface Foo { public void bar(String baz); }
. Alguém faz uma classe que invocabar
:someFoo.bar(baz = "hello");
. Eu mudo a assinatura deFoo::bar
parapublic void bar(String foobar)
. Agora, a pessoa que ligousomeFoo
precisará modificar seu código, se ainda quiser que ele funcione.Há muitas respostas boas aqui, mas nenhuma menciona que há implementações altamente otimizadas das classes / interfaces da API Collection especificamente para enumerações :
Essas classes específicas de enum aceitam apenas
Enum
instâncias (asEnumMap
únicasEnum
apenas como chaves) e, sempre que possível, elas revertem para compactar representação e manipulação de bits em sua implementação.O que isto significa?
Se nosso
Enum
tipo não tiver mais que 64 elementos (a maioria dosEnum
exemplos da vida real se qualificará para isso), as implementações armazenam os elementos em um únicolong
valor, cadaEnum
instância em questão será associada a um pouco desse comprimento de 64 bitslong
. Adicionar um elemento a umEnumSet
é simplesmente definir o bit apropriado como 1, removê-lo é apenas definir esse bit como 0. Testar se um elemento está noSet
é apenas um teste de máscara de bit ! Agora você tem amorEnum
por isso!fonte
What does this mean?
seção. Eu sabia que havia uma divisão na implementação no tamanho 64, mas eu realmente não sei por queexemplo:
Limitação de constantes java
1) Sem segurança de tipo : Primeiro de tudo, não é seguro de tipo; você pode atribuir qualquer valor int válido a int, por exemplo, 99, embora não exista uma moeda para representar esse valor.
2) Nenhuma impressão significativa : o valor de impressão de qualquer uma dessas constantes imprimirá seu valor numérico em vez do nome significativo da moeda; por exemplo, quando você imprime NICKLE, ele imprime "5" em vez de "NICKLE"
3) Sem espaço para nome : para acessar a constante currencyDenom, precisamos prefixar o nome da classe, por exemplo, CurrencyDenom.PENNY, em vez de apenas usar PENNY, embora isso também possa ser alcançado usando a importação estática no JDK 1.5
Vantagem de enum
1) As enums em Java são de tipo seguro e possuem um espaço de nome próprio. Isso significa que sua enumeração terá um tipo, por exemplo, "Moeda" no exemplo abaixo e você não poderá atribuir nenhum valor diferente do especificado em Constantes de enumeração.
Currency coin = Currency.PENNY; coin = 1; //compilation error
2) O Enum em Java é do tipo referência, como classe ou interface, e você pode definir construtor, métodos e variáveis dentro do Java Enum, o que o torna mais poderoso que o Enum em C e C ++, como mostra o próximo exemplo do tipo Java Enum.
3) Você pode especificar valores de constantes de enumeração no momento da criação, como mostrado no exemplo abaixo: enumeração pública Moeda {PENNY (1), NICKLE (5), DIME (10), QUARTER (25)}; Mas, para que isso funcione, você precisa definir uma variável de membro e um construtor porque PENNY (1) está realmente chamando um construtor que aceita o valor int, veja o exemplo abaixo.
Referência: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html
fonte
O primeiro benefício das enums, como você já notou, é a simplicidade da sintaxe. Mas o principal ponto de enumeração é fornecer um conjunto conhecido de constantes que, por padrão, formam um intervalo e ajudam a executar uma análise de código mais abrangente por meio de verificações de segurança de tipo e valor.
Esses atributos de enumerações ajudam um programador e um compilador. Por exemplo, digamos que você veja uma função que aceita um número inteiro. O que esse número inteiro pode significar? Que tipo de valores você pode transmitir? Você realmente não sabe imediatamente. Mas se você vê uma função que aceita enum, conhece muito bem todos os valores possíveis que pode transmitir.
Para o compilador, as enumerações ajudam a determinar um intervalo de valores e, a menos que você atribua valores especiais aos membros da enumeração, elas também variam de 0 a mais. Isso ajuda a rastrear automaticamente os erros no código por meio de verificações de segurança de tipo e muito mais. Por exemplo, o compilador pode avisá-lo de que você não manipula todos os valores possíveis de enumeração na instrução switch (ou seja, quando você não possui
default
maiúsculas e minúsculas e manipula apenas um dos valores de enum). Ele também avisa quando você converte um número inteiro arbitrário em enum porque o intervalo de valores do enum é menor que o número inteiro e que, por sua vez, pode desencadear erros na função que realmente não aceita um número inteiro. Além disso, a geração de uma tabela de salto para o comutador se torna mais fácil quando os valores são de 0 ou mais.Isso não é verdade apenas para Java, mas também para outras linguagens com uma rigorosa verificação de tipo. C, C ++, D, C # são bons exemplos.
fonte
Uma enum é implicitamente final; com construtores privados, todos os seus valores são do mesmo tipo ou sub-tipo; você pode obter todos os seus valores usando
values()
, obtém seuname()
ouordinal()
valor ou pode procurar uma enum por número ou nome.Você também pode definir subclasses (mesmo que nocionalmente final, algo que você não pode fazer de outra maneira)
fonte
enum Benefícios:
"como a capacidade de atribuir facilmente um elemento enum a um determinado valor"
"e, consequentemente, a capacidade de converter um número inteiro em uma enum sem uma quantidade razoável de esforço" Adicione um método que converta int em enum que faça isso. Apenas adicione HashMap estático <Inteiro, EnumX> contendo o mapeamento java enum .
Se você realmente deseja converter ord = VAL_200.ordinal () de volta em val_200, use: EnumX.values () [ord]
fonte
Outra diferença importante é que o compilador java trata
static final
campos de tipos primitivos e String como literais. Isso significa que essas constantes se tornam inline. É semelhante aoC/C++
#define
pré - processador. Veja esta pergunta SO . Este não é o caso de enums.fonte
Você obtém uma verificação do tempo de compilação de valores válidos quando você usa uma enumeração. Olhe para esta pergunta.
fonte
A maior vantagem é enum Os singletons são fáceis de escrever e seguros para threads:
e
ambos são semelhantes e lidou com a serialização por si mesmos, implementando
Mais
fonte
Eu acho
enum
que não pode serfinal
, porque sob o capô o compilador gera subclasses para cadaenum
entrada.Mais informações Da fonte
fonte
Há muitas vantagens de enumerações postadas aqui e estou criando essas enumerações agora, conforme solicitado na pergunta. Mas eu tenho um enum com 5-6 campos.
Nesses tipos de casos, quando você tem vários campos em enumerações, é muito difícil entender qual valor pertence a qual campo, pois você precisa ver o construtor e a bola ocular.
Classificar com
static final
constantes e usar oBuilder
padrão para criar esses objetos o torna mais legível. Mas você perderia todas as outras vantagens de usar uma enumeração, se precisar delas. Uma desvantagem de tais classes é que você precisa adicionar osPlanet
objetos manualmente aolist/set
dePlanets.
Eu ainda prefiro enum sobre essa classe, como
values()
vem a calhar e você nunca sabe se você precisar deles para usar emswitch
ouEnumSet
ouEnumMap
no futuro :)fonte
Razão principal: as enums ajudam você a escrever um código bem estruturado, onde o significado semântico dos parâmetros é claro e fortemente digitado em tempo de compilação - por todos os motivos que outras respostas deram.
Quid pro quo: no Java pronto para uso, a matriz de membros da Enum é final. Isso normalmente é bom, pois ajuda a valorizar a segurança e os testes, mas em algumas situações pode ser uma desvantagem, por exemplo, se você estiver estendendo o código base existente, talvez a partir de uma biblioteca. Por outro lado, se os mesmos dados estiverem em uma classe com campos estáticos, você poderá adicionar facilmente novas instâncias dessa classe em tempo de execução (também será necessário escrever código para adicioná-los a qualquer Iterável que você tiver para essa classe). Mas esse comportamento do Enums pode ser alterado: usando a reflexão, você pode adicionar novos membros em tempo de execução ou substituir membros existentes, embora isso provavelmente deva ser feito apenas em situações especializadas em que não há alternativa: por exemplo, é uma solução hacky e pode produzir problemas inesperados, veja minha resposta emPosso adicionar e remover elementos de enumeração em tempo de execução em Java .
fonte