O que são enums e por que são úteis?

488

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 enumvenho programando em Java há mais de alguns anos. E aparentemente eles mudaram muito. Agora eles até oferecem suporte total ao POO dentro de si.

Agora, por que e para quê devo usar enum na programação do dia a dia?

Mat B.
fonte
6
Em seu livro Effective Java, Second Edition , Joshua Bloch detalha essa abordagem no Item 3: Aplicar a propriedade Singleton com um construtor privado ou um tipo de enumeração , reimpresso no Dr. Dobb's .
precisa saber é o seguinte
possível duplicata do Enum em Java. Vantagens?
finnw
Você não pode instanciar enums porque ele possui construtor privado, eles são instanciados na inicialização da jvm, portanto, seu singleton, Enums não é seguro para threads.
Arnav Joshi

Respostas:

633

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?

/** Counts number of foobangs.
 * @param type Type of foobangs to count. Can be 1=green foobangs,
 * 2=wrinkled foobangs, 3=sweet foobangs, 0=all types.
 * @return number of foobangs of type
 */
public int countFoobangs(int type)

versus

/** Types of foobangs. */
public enum FB_TYPE {
 GREEN, WRINKLED, SWEET, 
 /** special type for all types combined */
 ALL;
}

/** Counts number of foobangs.
 * @param type Type of foobangs to count
 * @return number of foobangs of type
 */
public int countFoobangs(FB_TYPE type)

Uma chamada de método como:

int sweetFoobangCount = countFoobangs(3);

então se torna:

int sweetFoobangCount = countFoobangs(FB_TYPE.SWEET);

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

int sweetFoobangCount = countFoobangs(99);

não é mais possível.

sleske
fonte
41
Se você usa enumerações e deseja permitir uma combinação de valores, use EnumSet. Isso vem com todos os tipos de ajudantes legais, como final estático público EnumSet <FB_TYPE> ALL = EnumSet.allOf (FB_TYPE.class);
27413 RobAu
20
Essas respostas são as que mais gosto de ver na SO, porque alguém se esforçou bastante, bom trabalho agora entendo enums!
Dediqated
1
Eu não acho que isso seja verdade 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ógica or) pode ser útil para aplicativos em tempo real, onde você tem pouca memória.
Elist
O @Elist usando enums aumenta a legibilidade de seus códigos. Se você usa constantes em alguma parte do tempo, você ou seu sucessor não sabem por que ele é usado ...
:)
136

Por que usar qualquer recurso de linguagem de programação? A razão pela qual temos idiomas é para

  1. Programadores para expressar algoritmos de maneira eficiente e correta em um formato que os computadores podem usar.
  2. Mantenedores para entender algoritmos que outros escreveram e fazer alterações corretamente .

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:

public class Color {
    private Color() {} // Prevent others from making colors.
    public static final Color RED = new Color();
    public static final Color AMBER = new Color();
    public static final Color GREEN = new Color();
}

Agora você pode escrever:

Color trafficLightColor = Color.RED;

O padrão acima tem praticamente o mesmo efeito que

public enum Color { RED, AMBER, GREEN };

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 finalsimulação de enum acima não fornece é switchcasos 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 o enum Coloracima, você apenas precisa dizer:

Color color = ... ;
switch (color) {
    case RED:
        ...
        break;
}

Note que não está Color.REDnos casos. Se você não usar enum, a única maneira de usar quantidades nomeadas switché algo como:

public Class Color {
    public static final int RED = 0;
    public static final int AMBER = 1;
    public static final int GREEN = 2;
}

Mas agora uma variável para conter uma cor deve ter tipo int. A boa verificação do enum e da static finalsimulação pelo compilador se foi. Infeliz.

Um compromisso é usar um membro com valor escalar na simulação:

public class Color {
    public static final int RED_TAG = 1;
    public static final int AMBER_TAG = 2;
    public static final int GREEN_TAG = 3;

    public final int tag;

    private Color(int tag) { this.tag = tag; } 
    public static final Color RED = new Color(RED_TAG);
    public static final Color AMBER = new Color(AMBER_TAG);
    public static final Color GREEN = new Color(GREEN_TAG);
}

Agora:

Color color = ... ;
switch (color.tag) {
    case Color.RED_TAG:
        ...
        break;
}

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:

public class SingletonClass {
    public static final void INSTANCE = new SingletonClass();
    private SingletonClass() {}

    // all the methods and instance data for the class here
}

e depois acessá-lo com

SingletonClass.INSTANCE

podemos apenas dizer

public enum SingletonClass {
    INSTANCE;

    // all the methods and instance data for the class here
}

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: orde valuesetc. (na verdade, há uma simulação mais complicada em Color extends Integerque isso funcionará com o switch, mas é tão complicado que ainda mais mostra claramente por que enumé 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.

public class SingletonClass {
    private static SingletonClass INSTANCE;
    private SingletonClass() {}
    public SingletonClass getInstance() {
        if (INSTANCE == null) INSTANCE = new SingletonClass();
        return INSTANCE;
    }

    // all the methods and instance data for the class here
}

Se muitos threads chamarem getInstancesimultaneamente enquanto INSTANCEainda estiver nulo, qualquer número de instâncias poderá ser criado. Isto é mau. A única solução é adicionar synchronizedacesso para proteger a variável INSTANCE.

No entanto, o static finalcó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 enumsingleton é 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ância INSTANCE. 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.

Gene
fonte
15
Esse último parágrafo realmente esclareceu a situação do singleton para mim. Obrigado! Qualquer leitor que esteja pesquisando deve reler isso.
Basil Bourque
Eu estava lendo isso, stackoverflow.com/questions/16771373/… . Agora estou confuso com o seu último parágrafo. Como enum não fornece o recurso de inicialização por lay?
Deepankar Singh
static finalos campos são inicializados no momento da inicialização da classe , não no tempo de carregamento. É exatamente o mesmo que com enuma 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.
Holger
42

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:

  1. Ter o código onde estão os dados (ou seja, dentro do próprio enum - ou geralmente dentro das constantes do enum, que podem substituir os métodos).
  2. Implementar uma interface (ou mais) para não vincular o código do cliente à enumeração (que deve fornecer apenas um conjunto de implementações padrão).

O exemplo mais simples seria um conjunto de Comparatorimplementações:

enum StringComparator implements Comparator<String> {
    NATURAL {
        @Override
        public int compare(String s1, String s2) {
            return s1.compareTo(s2);
        }
    },
    REVERSE {
        @Override
        public int compare(String s1, String s2) {
            return NATURAL.compare(s2, s1);
        }
    },
    LENGTH {
        @Override
        public int compare(String s1, String s2) {
            return new Integer(s1.length()).compareTo(s2.length());
        }
    };
}

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 Granularityvisto pela camada de serviço era simplesmente uma interface.

Costi Ciudatu
fonte
2
Você também pode adicionar 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.
Holger
32

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()e hashCode()e implementar Serializablee Comparable.

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.

orangepips
fonte
23

De documentos Java -

Você deve usar tipos de enumeração sempre que precisar representar um conjunto fixo de constantes. Isso inclui tipos de enum naturais, como os planetas em nosso sistema solar e conjuntos de dados em que você conhece todos os valores possíveis em tempo de compilação - por exemplo, as opções em um menu, sinalizadores de linha de comando e assim por diante.

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.

CoolBeans
fonte
8
Você usaria uma enumeração para todos os 366 dias do ano? É um conjunto fixo (366) de constantes (os dias não estão mudando). Então, isso sugere que você deveria. : - / eu restringiria o tamanho do conjunto fixo.
precisa saber é o seguinte
2
@marcog Com um pouco de inteligência, talvez seja possível resumir os dias da semana e os dias de cada mês em um enum compacto.
James P.
1
Por falar em dias da semana… o DayOfWeekenum 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 ).
Basil Bourque
19

Agora, por que e para quê devo usar enum na programação do dia a dia?

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ê melhor Locale.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.

James P.
fonte
@ arnt Corrigi a gramática na pergunta também. Obrigado.
James P.
13

Enums 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, ou int, em vez de Enum, para constantes?

  1. O compilador não permitirá erros de digitação , nem valores fora do conjunto fixo, pois as enumerações são tipos por si só. Consequências:
    • Você não precisará escrever uma pré-condição (ou manual if) para garantir que seu argumento esteja no intervalo válido.
    • O tipo invariante é fornecido gratuitamente.
  2. Enums podem ter comportamento, assim como qualquer outra classe.
  3. Você provavelmente precisaria de uma quantidade semelhante de memória para usar Strings, de qualquer maneira (isso depende da complexidade do Enum).

Além disso, cada uma das Enuminstâ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.

afsantos
fonte
13

É útil saber que enumssão como as outras classes com Constantcampos e a private constructor.

Por exemplo,

public enum Weekday
{
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
} 

O compilador o compila da seguinte maneira;

class Weekday extends Enum
{
  public static final Weekday MONDAY  = new Weekday( "MONDAY",   0 );
  public static final Weekday TUESDAY = new Weekday( "TUESDAY ", 1 );
  public static final Weekday WEDNESDAY= new Weekday( "WEDNESDAY", 2 );
  public static final Weekday THURSDAY= new Weekday( "THURSDAY", 3 );
  public static final Weekday FRIDAY= new Weekday( "FRIDAY", 4 );
  public static final Weekday SATURDAY= new Weekday( "SATURDAY", 5 );
  public static final Weekday SUNDAY= new Weekday( "SUNDAY", 6 );

  private Weekday( String s, int i )
  {
    super( s, i );
  }

  // other methods...
}
Ao infinito
fonte
12

enumsignifica enum eration, isto é, menção (várias coisas) uma a uma.

Uma enumeração é um tipo de dados que contém um conjunto fixo de constantes.

OU

An enumé como um class, com um conjunto fixo de instâncias conhecidas em tempo de compilação.

Por exemplo:

public class EnumExample {
    interface SeasonInt {
        String seasonDuration();
    }

    private enum Season implements SeasonInt {
        // except the enum constants remaining code looks same as class
        // enum constants are implicitly public static final we have used all caps to specify them like Constants in Java
        WINTER(88, "DEC - FEB"), SPRING(92, "MAR - JUN"), SUMMER(91, "JUN - AUG"), FALL(90, "SEP - NOV");

        private int days;
        private String months;

        Season(int days, String months) { // note: constructor is by default private 
            this.days = days;
            this.months = months;
        }

        @Override
        public String seasonDuration() {
            return this+" -> "+this.days + "days,   " + this.months+" months";
        }

    }
    public static void main(String[] args) {
        System.out.println(Season.SPRING.seasonDuration());
        for (Season season : Season.values()){
            System.out.println(season.seasonDuration());
        }

    }
}

Vantagens do enum:

  • enum melhora a segurança de tipo na verificação em tempo de compilação para evitar erros em tempo de execução.
  • enum pode ser facilmente usado no switch
  • enum pode ser atravessado
  • enum pode ter campos, construtores e métodos
  • enum pode implementar muitas interfaces, mas não pode estender nenhuma classe, porque estende internamente a classe Enum

para mais

Premraj
fonte
9

O que é um enum

  • enum é uma palavra-chave definida para Enumeração, um novo tipo de dados. As enumerações Typesafe devem ser usadas liberalmente. Em particular, são uma alternativa robusta às constantes String ou int simples usadas em APIs muito mais antigas para representar conjuntos de itens relacionados.

Por que usar enum

  • enums são subclasses implicitamente finais de java.lang.Enum
  • se um enum é membro de uma classe, é implicitamente estático
  • new nunca pode ser usado com um enum, mesmo dentro do próprio tipo de enum
  • name e valueOf simplesmente use o texto das constantes enum, enquanto toString pode ser substituído para fornecer qualquer conteúdo, se desejado
  • para constantes enum, iguais e == equivalem à mesma coisa e podem ser usados ​​de forma intercambiável
  • constantes enum são final estático implicitamente público

Nota

  • enums não podem estender nenhuma classe.
  • Um enum não pode ser uma superclasse.
  • a ordem de aparência das constantes enum é chamada de "ordem natural" e também define a ordem usada por outros itens: compareTo, ordem de iteração dos valores, EnumSet, EnumSet.range.
  • Uma enumeração pode ter construtores, estáticos e blocos de instância, variáveis ​​e métodos, mas não pode ter métodos abstratos.
tinker_fairy
fonte
4
Você não explica por que usar enums. Você apenas lista várias propriedades de enumerações em cabeçalhos não relacionados.
Duncan Jones
@DuncanJones os termos final, estático não fornecem o objetivo de usar enumerações?
Tinker_fairy
8

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 enumnos métodos estáticos para obter enumobjetos valuee vice-versa. O código parecia mais limpo, alternava a usabilidade de maiúsculas e minúsculas e escrevia mais facilmente nos logs.

enum ProtocolType {
    TCP_IP (1, "Transmission Control Protocol"), 
    IP (2, "Internet Protocol"), 
    UDP (3, "User Datagram Protocol");

    public int code;
    public String name;

    private ProtocolType(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public static ProtocolType fromInt(int code) {
    switch(code) {
    case 1:
        return TCP_IP;
    case 2:
        return IP;
    case 3:
        return UDP;
    }

    // we had some exception handling for this
    // as the contract for these was between 2 independent applications
    // liable to change between versions (mostly adding new stuff)
    // but keeping it simple here.
    return null;
    }
}

Crie um enumobjeto a partir dos valores recebidos (por exemplo, 1,2) usando ProtocolType.fromInt(2) Gravar nos logs usandomyEnumObj.name

Espero que isto ajude.

sErVerdevIL
fonte
6

Enum herda todos os métodos de Objectclasse e classe abstrata Enum. 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.

public enum State {

    Start("1"),
    Wait("1"),
    Notify("2"),
    NotifyAll("3"),
    Run("4"),
    SystemInatilize("5"),
    VendorInatilize("6"),
    test,
    FrameworkInatilize("7");

    public static State getState(String value) {
        return State.Wait;
    }

    private String value;
    State test;

    private State(String value) {
        this.value = value;
    }

    private State() {
    }

    public String getValue() {
        return value;
    }

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public boolean isNotify() {
        return this.equals(Notify);
    }
}

public class EnumTest {

    State test;

    public void setCurrentState(State currentState) {
        test = currentState;
    }

    public State getCurrentState() {
        return test;
    }

    public static void main(String[] args) {
        System.out.println(State.test);
        System.out.println(State.FrameworkInatilize);
        EnumTest test=new EnumTest();
        test.setCurrentState(State.Notify);
        test. stateSwitch();
    }

    public void stateSwitch() {
        switch (getCurrentState()) {
        case Notify:
            System.out.println("Notify");
            System.out.println(test.isNotify());
            break;
        default:
            break;
        }
    }
}
abishkar bhattarai
fonte
4

ENum significa "Tipo enumerado". É um tipo de dados com um conjunto fixo de constantes que você define.

Steve
fonte
Você não explicou por que usar uma enumeração.
Duncan Jones
4
Sim eu fiz. Você o utiliza para armazenar um conjunto fixo de constantes que você mesmo define. A aplicação específica depende de você. Não existe quando dizer quando, por que ou como usar alguma coisa. Isso depende das necessidades do desenvolvedor. Tudo o que você precisa entender é o que é e como funciona.
25413 Steve
4

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.

Rafa
fonte
3

Use enumerações para TYPE SAFETY, este é um recurso de idioma, para que você normalmente obtenha:

  • Suporte ao compilador (consulte imediatamente problemas de tipo)
  • Suporte de ferramenta em IDEs (preenchimento automático em caso de switch, casos ausentes, forçar padrão, ...)
  • Em alguns casos, o desempenho do enum também é ótimo ( EnumSet , uma alternativa segura para os tradicionais "sinalizadores de bits" baseados em int ).

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 .

Christophe Roussy
fonte
2

Java permite restringir a variável a ter apenas um dos poucos valores predefinidos - em outras palavras, um valor de uma lista enumerada. Usar enumspode ajudar a reduzir erros no seu código. Aqui está um exemplo de enumsfora de uma classe:

enums coffeesize{BIG , HUGE , OVERWHELMING }; 
//This semicolon is optional.

Isto restringe coffeesizea ter quer: BIG, HUGE, ou OVERWHELMINGcomo uma variável.

Rahul Prajapat
fonte
2

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:

public enum operation {
    create("1")
    delete("2")
    edit("3")
    read("4")

    // You may have is methods here
    public boolean isCreate() {
        return this.equals(create);
    }
    // More methods like the above can be written

}

Agora, você pode declarar algo como:

private operation currentOperation;

// And assign the value for it 
currentOperation = operation.create

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. :)

Abhishek Bhandari
fonte
1

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.

happybuddha
fonte
1

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:

enum RGB {
    RED("Red"), GREEN("Green"), BLUE("Blue");

    public static final String PREFIX = "color ";

    public String getRGBString() {
        return PREFIX + color;
    }

    String color;

    RGB(String color) {
        this.color = color;
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        String c = RGB.RED.getRGBString();
        System.out.print("Hello " + c);
    }
}
djangofan
fonte
1

Quanto a tornar o código legível no futuro, o caso útil de enumeração mais útil é representado no próximo trecho:

public enum Items {
    MESSAGES, CHATS, CITY_ONLINE, FRIENDS, PROFILE, SETTINGS, PEOPLE_SEARCH, CREATE_CHAT
}

@Override
public boolean onCreateOptionsMenu(Menu menuPrm) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menuPrm);
    View itemChooserLcl;
    for (int i = 0; i < menuPrm.size(); i++) {
        MenuItem itemLcl  = menuPrm.getItem(i);
            itemChooserLcl = itemLcl.getActionView();
            if (itemChooserLcl != null) {
                 //here Im marking each View' tag by enume values:
                itemChooserLcl.setTag(Items.values()[i]);
                itemChooserLcl.setOnClickListener(drawerMenuListener);
            }
        }
    return true;
}
private View.OnClickListener drawerMenuListener=new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Items tagLcl= (Items) v.getTag();
        switch (tagLcl){
            case MESSAGES: ;
            break;
            case CHATS : ;
            break;
            case CITY_ONLINE : ;
            break;
            case FRIENDS : ;
            break;
            case  PROFILE: ;
            break;
            case  SETTINGS: ;
            break;
            case  PEOPLE_SEARCH: ;
            break;
            case  CREATE_CHAT: ;
            break;
        }
    }
};
CodeToLife
fonte
1

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

BradB
fonte
1

O singleton baseado em enum

uma visão moderna de um problema antigo

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.

public enum Singleton {
    SINGLETON; 
    public void method() { }
}

Como é que isso funciona? Bem, a linha dois do código pode ser considerada algo como isto:

public final static Singleton SINGLETON = new Singleton(); 

E temos um bom e velho singleton inicializado cedo.

Lembre-se de que, como esse é um enum, você sempre pode acessar a instância Singleton.INSTANCEtambém:

Singleton s = Singleton.INSTANCE;
Vantagens
  • Para impedir a criação de outras instâncias de singleton durante a desserialização, use singleton baseado em enum porque a serialização de enum é realizada pela JVM. A serialização e a desserialização de enum funcionam de maneira diferente da dos objetos java normais. A única coisa que é serializada é o nome do valor da enumeração. Durante o processo de desserialização, o valueOfmétodo enum é usado com o nome desserializado para obter a instância desejada.
  • O singleton baseado em enum permite proteger-se do ataque de reflexão. O tipo de enum realmente estende a Enumclasse 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 do newInstancemétodo da Constructorclasse, que geralmente é usada para criar objetos via reflexão:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
  • Enum não deve ser clonado porque deve haver exatamente uma instância de cada valor.
  • O código mais lacônico entre todas as realizações singleton.
Desvantagens
  • O singleton baseado em enum não permite inicialização lenta.
  • Se você alterasse seu design e desejasse converter seu singleton em multiton, o enum não permitiria isso. O padrão multiton é usado para a criação controlada de várias instâncias, gerenciadas pelo uso de a map. Em vez de ter uma única instância por aplicativo (por exemplo, o java.lang.Runtime), o padrão multiton garante uma única instância por chave .
  • O enum aparece apenas no Java 5, portanto você não pode usá-lo na versão anterior.

Existem várias realizações do padrão singleton, cada uma com vantagens e desvantagens.

  • Ansioso de carregamento ansioso
  • Singleton de bloqueio verificado duas vezes
  • Idioma do detentor de inicialização sob demanda
  • O singleton baseado em enum

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

Oleg Poltoratskii
fonte
0

Eu usaria enums como um instrumento de mapeamento útil, evitando múltiplos, if-else desde que alguns métodos sejam implementados.

public enum Mapping {

    ONE("1"),
    TWO("2");

    private String label;

    private Mapping(String label){
        this.label = label;
    }

    public static Mapping by(String label) {

        for(Mapping m: values() {
            if(m.label.equals(label)) return m;
        }

        return null;
    }

}

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 um mainmétodo dentro dele, o que pode ser útil quando você precisar executar algumas operações de mapeamento argsimediatamente.

TEH EMPRAH
fonte
0

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

Vincent Tang
fonte
0

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.

Shetu
fonte
0

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 .

Nicolas Voron
fonte