Hoje, eu estava navegando por algumas perguntas neste site e encontrei uma menção a enum
ser usado no padrão singleton sobre os supostos benefícios de segurança de threads para essa solução.
Eu nunca usei se enum
venho programando em Java há mais de alguns anos. E aparentemente eles mudaram muito. Agora eles até oferecem suporte total ao POO dentro de si.
Respostas:
Você sempre deve usar enumerações quando uma variável (especialmente um parâmetro de método) pode tirar apenas uma dentre um pequeno conjunto de valores possíveis. Exemplos seriam coisas como constantes de tipo (status do contrato: "permanente", "temp", "aprendiz") ou sinalizadores ("execute agora", "adie a execução").
Se você usar enumerações em vez de números inteiros (ou códigos de Cadeia de Caracteres), aumentará a verificação em tempo de compilação e evitará erros de transmitir constantes inválidas e documentará quais valores são legais para usar.
BTW, o uso excessivo de enumerações pode significar que seus métodos fazem muito (geralmente é melhor ter vários métodos separados, em vez de um método que usa vários sinalizadores que modificam o que ele faz), mas se você precisar usar sinalizadores ou códigos de tipo, enumerações são o caminho a percorrer.
Como exemplo, qual é o melhor?
versus
Uma chamada de método como:
então se torna:
No segundo exemplo, fica claro imediatamente quais tipos são permitidos, documentos e implementação não podem sair de sincronia e o compilador pode impor isso. Além disso, uma chamada inválida como
não é mais possível.
fonte
you should *always* use enums when a variable can only take one out of a small set of possible values
. Usar valores constantes como 'sinalizador binário' (com lógicaor
) pode ser útil para aplicativos em tempo real, onde você tem pouca memória.Por que usar qualquer recurso de linguagem de programação? A razão pela qual temos idiomas é para
As enums aumentam a probabilidade de correção e legibilidade sem escrever muito clichê. Se você estiver disposto a escrever um texto padrão, poderá "simular" enumerações:
Agora você pode escrever:
O padrão acima tem praticamente o mesmo efeito que
Ambos fornecem o mesmo nível de verificação de ajuda do compilador. Boilerplate é apenas mais digitação. Mas economizar muita digitação torna o programador mais eficiente (consulte 1), por isso é um recurso que vale a pena.
Também vale a pena por pelo menos mais um motivo:
Instruções de troca
Uma coisa que a
static final
simulação de enum acima não fornece éswitch
casos agradáveis . Para tipos de enum, o comutador Java usa o tipo de sua variável para inferir o escopo dos casos de enum, portanto, para oenum Color
acima, você apenas precisa dizer:Note que não está
Color.RED
nos casos. Se você não usar enum, a única maneira de usar quantidades nomeadasswitch
é algo como:Mas agora uma variável para conter uma cor deve ter tipo
int
. A boa verificação do enum e dastatic final
simulação pelo compilador se foi. Infeliz.Um compromisso é usar um membro com valor escalar na simulação:
Agora:
Mas observe, ainda mais clichê!
Usando uma enumeração como um singleton
No boilerplate acima, você pode ver por que uma enum fornece uma maneira de implementar um singleton. Em vez de escrever:
e depois acessá-lo com
podemos apenas dizer
o que nos dá a mesma coisa. Podemos nos safar disso porque as enums do Java são implementadas como classes completas, com apenas um pouco de açúcar sintático espalhado por cima. Isso é novamente menos elaborado, mas não é óbvio, a menos que o idioma lhe seja familiar. Também não gosto do fato de que você obtém as várias funções enum, mesmo que elas não façam muito sentido para o singleton:
ord
evalues
etc. (na verdade, há uma simulação mais complicada emColor extends Integer
que isso funcionará com o switch, mas é tão complicado que ainda mais mostra claramente por queenum
é uma ideia melhor.)Segurança da linha
A segurança do encadeamento é um problema em potencial somente quando singletons são criados preguiçosamente sem travamento.
Se muitos threads chamarem
getInstance
simultaneamente enquantoINSTANCE
ainda estiver nulo, qualquer número de instâncias poderá ser criado. Isto é mau. A única solução é adicionarsynchronized
acesso para proteger a variávelINSTANCE
.No entanto, o
static final
código acima não tem esse problema. Ele cria a instância ansiosamente no tempo de carregamento da classe. O carregamento da classe é sincronizado.O
enum
singleton é efetivamente preguiçoso porque não é inicializado até o primeiro uso. A inicialização do Java também é sincronizada, portanto, vários encadeamentos não podem inicializar mais de uma instânciaINSTANCE
. Você está recebendo um singleton inicializado preguiçosamente com muito pouco código. O único aspecto negativo é a sintaxe bastante obscura. Você precisa conhecer o idioma ou entender completamente como o carregamento e a inicialização da classe funcionam para saber o que está acontecendo.fonte
static final
os campos são inicializados no momento da inicialização da classe , não no tempo de carregamento. É exatamente o mesmo que comenum
a inicialização constante (na verdade, eles são idênticos sob o capô). É por isso que tentar implementar código de inicialização lento “inteligente” para singletons sempre foi inútil, mesmo na primeira versão do Java.Além dos casos de uso já mencionados, muitas vezes considero enumerações úteis para implementar o padrão de estratégia, seguindo algumas diretrizes básicas de POO:
O exemplo mais simples seria um conjunto de
Comparator
implementações:Esse "padrão" pode ser usado em cenários muito mais complexos, fazendo uso extensivo de todos os presentes que vêm com a enum: iterando pelas instâncias, baseando-se em sua ordem implícita, recuperando uma instância pelo nome, métodos estáticos fornecendo a instância correta para contextos específicos etc. E ainda assim você tem tudo isso oculto por trás da interface, para que seu código funcione com implementações personalizadas sem modificação, caso você queira algo que não esteja disponível entre as "opções padrão".
Eu já vi isso aplicado com sucesso para modelar o conceito de granularidade do tempo (diariamente, semanalmente etc.) em que toda a lógica foi encapsulada em um enum (escolhendo a granularidade correta para um determinado intervalo de tempo, comportamento específico vinculado a cada granularidade como constante métodos etc.). E, ainda assim, o
Granularity
visto pela camada de serviço era simplesmente uma interface.fonte
CASE_INSENSITIVE { @Override public int compare(String s1, String s2) { return s1.compareToIgnoreCase(s2); }
. Uma vantagem ainda não mencionada é que você recebe um suporte robusto de serialização; o formulário persistente contém apenas o nome da classe e o nome constante, não dependendo de nenhum detalhe de implementação dos seus comparadores.Algo que nenhuma das outras respostas abordou que tornam as enums particularmente poderosas é a capacidade de ter métodos de modelo . Os métodos podem fazer parte do enum base e serem substituídos por cada tipo. E, com o comportamento associado ao enum, muitas vezes elimina a necessidade de construções if-else ou instruções de troca, como demonstra esta postagem do blog - onde
enum.method()
é que o que originalmente seria executado dentro do condicional. O mesmo exemplo também mostra o uso de importações estáticas com enumerações, além de produzir códigos DSL muito mais limpos.Algumas outras qualidades interessantes incluem o fato de que enums fornecer implementação para
equals()
,toString()
ehashCode()
e implementarSerializable
eComparable
.Para um resumo completo de tudo o que as enums têm a oferecer, recomendo o Thinking in Java 4th edition, de Bruce Eckel, que dedica um capítulo inteiro ao tópico. Particularmente esclarecedores são os exemplos que envolvem um jogo de Pedra, Papel, Tesoura (ou seja, RoShamBo) como enums.
fonte
De documentos Java -
Um exemplo comum é substituir uma classe por um conjunto de constantes int estáticas privadas (dentro de um número razoável de constantes) por um tipo de enumeração. Basicamente, se você acha que conhece todos os valores possíveis de "algo" no momento da compilação, pode representá-lo como um tipo de enumeração. Enums fornecem legibilidade e flexibilidade sobre uma classe com constantes.
Algumas outras vantagens que consigo pensar nos tipos de enumeração. Eles sempre são uma instância de uma classe enum específica (daí o conceito de usar enumerações como singleton chega). Outra vantagem é que você pode usar enumerações como um tipo na instrução de caso de troca. Além disso, você pode usar toString () na enumeração para imprimi-los como cadeias legíveis.
fonte
DayOfWeek
enum agora está pré-definido, incorporado ao Java 8 e posterior como parte da estrutura java.time (e com porta traseira para Java 6 e 7 e Android ).Você pode usar um Enum para representar um conjunto fixo pequeno de constantes ou um modo de classe interno enquanto aumenta a legibilidade. Além disso, as enums podem impor uma certa rigidez quando usadas nos parâmetros do método. Eles oferecem a possibilidade interessante de passar informações para um construtor, como no exemplo de Planetas no site da Oracle e, como você descobriu, também permitem uma maneira simples de criar um padrão singleton.
ex:
Locale.setDefault(Locale.US)
lê melhorLocale.setDefault(1)
e reforça o uso do conjunto fixo de valores mostrado em um IDE quando você adiciona o.
separador em vez de todos os números inteiros.fonte
Enum
s enumera um conjunto fixo de valores, de maneira autodocumentada.Eles tornam seu código mais explícito e também menos propenso a erros.
Por que não usar
String
, ouint
, em vez deEnum
, para constantes?if
) para garantir que seu argumento esteja no intervalo válido.String
s, de qualquer maneira (isso depende da complexidade doEnum
).Além disso, cada uma das
Enum
instâncias é uma classe, para a qual você pode definir seu comportamento individual.Além disso, eles garantem a segurança do encadeamento após a criação das instâncias (quando o enum é carregado), o que tem sido ótimo para simplificar o Padrão Singleton .
Este blog ilustra alguns de seus aplicativos, como uma Máquina de Estado para um analisador.
fonte
É útil saber que
enums
são como as outras classes comConstant
campos e aprivate constructor
.Por exemplo,
O compilador o compila da seguinte maneira;
fonte
enum
significa enum eration, isto é, menção (várias coisas) uma a uma.OU
Por exemplo:
Vantagens do enum:
para mais
fonte
O que é um enum
Por que usar enum
Nota
fonte
Além de tudo o que foi dito por outros. Em um projeto antigo em que eu costumava trabalhar, muita comunicação entre entidades (aplicativos independentes) estava usando números inteiros, o que representava um pequeno conjunto. Foi útil declarar o conjunto como
enum
nos métodos estáticos para obterenum
objetosvalue
e vice-versa. O código parecia mais limpo, alternava a usabilidade de maiúsculas e minúsculas e escrevia mais facilmente nos logs.Crie um
enum
objeto a partir dos valores recebidos (por exemplo, 1,2) usandoProtocolType.fromInt(2)
Gravar nos logs usandomyEnumObj.name
Espero que isto ajude.
fonte
Enum herda todos os métodos de
Object
classe e classe abstrataEnum
. Então você pode usar seus métodos para reflexão, multithreading, serilização, comparável etc. Se você apenas declarar uma constante estática em vez de Enum, não poderá. Além disso, o valor de Enum também pode ser passado para a camada DAO.Aqui está um exemplo de programa para demonstrar.
fonte
ENum significa "Tipo enumerado". É um tipo de dados com um conjunto fixo de constantes que você define.
fonte
Na minha opinião, todas as respostas que você conseguiu até agora são válidas, mas, na minha experiência, eu expressaria isso em poucas palavras:
Use enumerações se desejar que o compilador verifique a validade do valor de um identificador.
Caso contrário, você poderá usar as strings como sempre fez (provavelmente definiu algumas "convenções" para o seu aplicativo) e será muito flexível ... mas não terá 100% de segurança contra erros de digitação nas suas strings e só as perceberá. em tempo de execução.
fonte
Use enumerações para TYPE SAFETY, este é um recurso de idioma, para que você normalmente obtenha:
Enums podem ter métodos, construtores, você pode até usar enums dentro de enums e combinar enums com interfaces.
Pense nas enumerações como tipos para substituir um conjunto bem definido de constantes int (que o Java 'herdou' do C / C ++) e, em alguns casos, para substituir os sinalizadores de bits.
O livro Effective Java 2nd Edition tem um capítulo inteiro sobre eles e entra em mais detalhes. Veja também esta postagem Stack Overflow .
fonte
Java permite restringir a variável a ter apenas um dos poucos valores predefinidos - em outras palavras, um valor de uma lista enumerada. Usar
enums
pode ajudar a reduzir erros no seu código. Aqui está um exemplo deenums
fora de uma classe:Isto restringe
coffeesize
a ter quer:BIG
,HUGE
, ouOVERWHELMING
como uma variável.fonte
Enum? Por que deveria ser usado? Eu acho que é mais compreendido quando você vai usá-lo. Eu tenho a mesma experiência.
Digamos que você tenha uma operação de criação, exclusão, edição e leitura de banco de dados.
Agora, se você criar uma enumeração como uma operação:
Agora, você pode declarar algo como:
Então você pode usá-lo de várias maneiras. É sempre bom ter enum para coisas específicas, pois a operação do banco de dados no exemplo acima pode ser controlada verificando o currentOperation . Talvez se possa dizer que isso também pode ser realizado com variáveis e valores inteiros. Mas acredito que o Enum é uma maneira mais segura e de programador.
Outra coisa: acho que todo programador adora booleano , não é? Porque ele pode armazenar apenas dois valores, dois valores específicos. Portanto, o Enum pode ser considerado como tendo o mesmo tipo de instalações em que um usuário definirá quantos e que tipo de valor armazenará, apenas de uma maneira um pouco diferente. :)
fonte
Até agora, eu nunca precisei usar enums. Eu tenho lido sobre eles desde que foram introduzidos no 1.5 ou versão tigre, como era chamado de volta no dia. Eles nunca realmente resolveram um 'problema' para mim. Para aqueles que o usam (e vejo muitos deles o fazem), tenho certeza de que definitivamente serve a algum propósito. Apenas meus 2 libras.
fonte
Há muitas respostas aqui, só quero apontar duas específicas:
1) Usando como constantes na
Switch-case
declaração. Alternar maiúsculas e minúsculas não permitirá que você use objetos String para maiúsculas e minúsculas. Enums são úteis. Mais: http://www.javabeat.net/2009/02/how-to-use-enum-in-switch/2) Implementação
Singleton Design Pattern
- Enum novamente, vem resgatar. Uso, aqui: Qual é a melhor abordagem para usar um Enum como um singleton em Java?fonte
O que me deu o momento Ah-Ha foi essa percepção: que o Enum tem um construtor privado acessível apenas através da enumeração pública:
fonte
Quanto a tornar o código legível no futuro, o caso útil de enumeração mais útil é representado no próximo trecho:
fonte
Na minha experiência, vi o uso do Enum às vezes fazer com que os sistemas sejam muito difíceis de mudar. Se você estiver usando um Enum para um conjunto de valores específicos de domínio que são alterados com freqüência, e ele tem muitas outras classes e componentes que dependem dele, convém considerar não usar um Enum.
Por exemplo, um sistema de negociação que usa um Enum para mercados / trocas. Existem muitos mercados por aí e é quase certo que haverá muitos subsistemas que precisam acessar essa lista de mercados. Toda vez que você deseja que um novo mercado seja adicionado ao seu sistema ou se você deseja remover um mercado, é possível que tudo que estiver exposto ao sol tenha que ser reconstruído e liberado.
Um exemplo melhor seria algo como um tipo de categoria de produto. Digamos que seu software gerencia o inventário de uma loja de departamentos. Existem muitas categorias de produtos e muitos motivos pelos quais essa lista de categorias pode mudar. Os gerentes podem querer estocar uma nova linha de produtos, livrar-se de outras linhas de produtos e possivelmente reorganizar as categorias periodicamente. Se você precisar reconstruir e reimplementar todos os seus sistemas simplesmente porque os usuários desejam adicionar uma categoria de produto, você adotou algo que deveria ser simples e rápido (adicionando uma categoria) e tornou muito difícil e lento.
Bottom line, Enums são bons se os dados que você está representando são muito estáticos ao longo do tempo e têm um número limitado de dependências. Mas se os dados mudarem muito e tiverem muitas dependências, você precisará de algo dinâmico que não seja verificado no tempo de compilação (como uma tabela de banco de dados).
fonte
O singleton baseado em enum
Essa abordagem implementa o singleton aproveitando a garantia do Java de que qualquer valor de enum seja instanciado apenas uma vez em um programa Java e o enum fornece suporte implícito à segurança do encadeamento. Como os valores de enum do Java são acessíveis globalmente, ele pode ser usado como o singleton.
Como é que isso funciona? Bem, a linha dois do código pode ser considerada algo como isto:
E temos um bom e velho singleton inicializado cedo.
Lembre-se de que, como esse é um enum, você sempre pode acessar a instância
VantagensSingleton.INSTANCE
também:valueOf
método enum é usado com o nome desserializado para obter a instância desejada.Enum
classe java . A razão pela qual a reflexão não pode ser usada para instanciar objetos do tipo enum é porque a especificação java não permite e essa regra é codificada na implementação donewInstance
método daConstructor
classe, que geralmente é usada para criar objetos via reflexão:map
. Em vez de ter uma única instância por aplicativo (por exemplo, ojava.lang.Runtime
), o padrão multiton garante uma única instância por chave .Existem várias realizações do padrão singleton, cada uma com vantagens e desvantagens.
Descrição detalhada de cada uma delas é muito detalhada, por isso, basta colocar um link para um bom artigo - Tudo o que você quer saber sobre Singleton
fonte
Eu usaria enums como um instrumento de mapeamento útil, evitando múltiplos,
if-else
desde que alguns métodos sejam implementados.Portanto, o método
by(String label)
permite que você obtenha o valor Enumerado por não enumerado. Além disso, pode-se inventar o mapeamento entre 2 enumerações. Também pode tentar '1 para muitos' ou 'muitos para muitos', além da relação padrão de 'um para um'No final,
enum
é uma classe Java. Portanto, você pode ter ummain
método dentro dele, o que pode ser útil quando você precisar executar algumas operações de mapeamentoargs
imediatamente.fonte
Em vez de fazer várias declarações const int
Você pode agrupá-los todos em 1 enum
Então, é tudo organizado pelo grupo comum ao qual pertencem
fonte
Enums são como classes. Como a classe, também possui métodos e atributos.
As diferenças de classe são: 1. As constantes enum são públicas, estáticas, finais. 2. Um enum não pode ser usado para criar um objeto e não pode estender outras classes. Mas ele pode implementar interfaces.
fonte
Além da resposta @BradB:
Isso é tão verdade ... É estranho que seja a única resposta que menciona isso. Quando os iniciantes descobrem enumerações, eles rapidamente tomam isso como um truque de mágica para verificação de identificador válido para o compilador. E quando o código se destina a ser usado em sistemas distribuídos, eles choram ... um mês depois. Manter a compatibilidade com versões anteriores de enumerações que contém uma lista não estática de valores é uma preocupação e um problema. Isso ocorre porque quando você adiciona um valor a uma enumeração existente, seu tipo é alterado (apesar do nome não).
"Ho, espere, pode parecer do mesmo tipo, certo? Afinal, eles são enums com o mesmo nome - e enums não são apenas números inteiros sob o capô?" E por esses motivos, seu compilador provavelmente não sinalizará o uso de uma definição do tipo em si onde estava esperando a outra. Mas, de fato, eles são (da maneira mais importante) tipos diferentes. Mais importante ainda, eles têm domínios de dados diferentes - valores aceitáveis de acordo com o tipo. Ao adicionar um valor, alteramos efetivamente o tipo de enum e, portanto, quebramos a compatibilidade com versões anteriores.
Concluindo: use-o quando quiser, mas verifique se o domínio de dados usado é um conjunto fixo finito, já conhecido .
fonte