enum.values ​​() - é uma ordem de enums retornada determinística


105

Eu tenho um enum SOME_ENUM:

public enum SOME_ENUM {
  EN_ONE,
  EN_TWO,
  EN_THREE;
}

Vai SOME_ENUM.values()sempre devolver os enums na ordem das declarações enum: EN_ONE, EN_TWO, EN_THREE? É uma regra ou não é garantido que não seja alterado nas próximas versões do JDK?


1
Eu itero sobre meu enum para preencher uma lista que, em vez de em outro lugar no código, li iterando sobre este enum.
Skarab

11
@MitchWheat Pela mesma razão que você confiaria em uma ordem de preservação de Lista: porque o JDK é uma ferramenta que oferece certas garantias e confiar nessas garantias o ajuda a escrever um código mais sucinto e melhor. É certo que a pergunta "É garantido que não será alterado?" é impossível responder, certamente não se pode confiar nisso, nada tem essa garantia.
Fletch

Respostas:


144

A especificação da linguagem Java usa esta linguagem explícita:

@return um array contendo as constantes deste tipo de enum, na ordem em que são declaradas [Source]

Então, sim, eles serão devolvidos na ordem de declaração. É importante notar que a ordem pode mudar com o tempo se alguém mudar a classe, portanto, tenha muito cuidado ao usar isso.


1
Se alguém adicionar um valor no meio em uma versão posterior do código, isso pode manchar você, pois mudaria o valor ordinal de outros elementos (consulte o método Enum.ordinal ()). É melhor não confiar na posição ordinal como um mecanismo de serialização (ou seja, não a armazene no banco de dados) por esse motivo.
Matt

1
Link para a fonte dessa especificação?
Dan Grahn


16

Sim, é garantido devolvê-los nessa ordem.

No entanto, você deve evitar confiar nisso e no ordinal()valor, pois ele pode mudar após a inserção de novos itens, por exemplo.


1 para o conselho sábio. No tópico de ordinal (), Effective Java sugere adicionar um campo de membro ao tipo enum.
ide

9

É determinado pela ordem em que seus valores são declarados. No entanto, não há garantia de que você (ou outra pessoa) não reordene / insira / remova valores no futuro . Portanto, você não deve confiar na ordem.

Java 2 eficaz. Edition dedica seu item 31 a um tópico intimamente relacionado: Use campos de instância em vez de ordinais :

Nunca derivar um valor associado a um enum de seu ordinal; armazene-o em um campo de instância.


3
"nenhuma garantia de que alguém não reordene os valores no futuro" - mas é exatamente por isso que eu quero confiar no pedido :-)! Quero ser capaz de reordenar os itens no futuro e, assim, mudar o comportamento do meu programa. Bloch está certo sobre não confiar no ordinal e se o exemplo do autor da pergunta realmente envolve enums como EN_TWO, então ele está confiando no ordinal e não deveria fazer isso. Mas confiar na ordem está perfeitamente bem. Na verdade, como o pedido é garantido, criar um campo especificamente para o pedido seria escrever código redundante, o tipo de coisa que livros como Java Efetivo dizem para você não fazer.
Fletch

@Fletch, desculpe, não estou entendendo bem. Para mim, isso soa como se você estivesse tentando usar enumpara algum propósito ao qual não foi planejado.
Péter Török

digamos que você tenha o famoso enum "Planeta". Em sua IU, você deseja listar os planetas na ordem de sua distância do sol. Qual a melhor forma de conseguir isso? Eu ordenaria as constantes planetárias na ordem correta dentro da classe enum e, em seguida, apenas enumeraria o enum na IU. Como o pedido é confiável, isso funcionará. É desse tipo de coisa que estou falando. Se um dia a Terra se mover mais perto do Sol do que Marte, é claro que nesse momento a primeira coisa em sua mente quente será manter seu código! Então você vai para a sua classe Planeta e move TERRA para antes de MARTE.
Fletch de

@Fletch, a Terra já está mais perto do Sol do que de Marte ;-) mas entendi o que você quis dizer. No entanto, neste caso, a ordem dos planetas é na verdade uma função de sua distância média do Sol, que não é um ordinal simples, portanto, IMHO deve ser melhor armazenado como um campo distinto para cada planeta. Em seguida, você pode ter um comparador trivial para comparar planetas com base em sua distância média do Sol e ordená-los usando este comparador. Este é IMHO uma solução limpa e infalível. Considerando que sua solução quebra assim que, por exemplo, um novo colega decide que os planetas devem obviamente ser listados em ordem alfabética ;-)
Péter Török

1
Hahaha ermm sim bem de qualquer maneira é tudo uma conspiração, não existe Marte. Inicialmente, eu ia usar Saturno, mas não conseguia lembrar de quais planetas ele está próximo, mas o plano de Marte parece ter saído pela culatra :-). Enfim ... neste caso um comparador seria bom, mas tem a desvantagem de exigir mais código, obviamente. Acho que se você está contando com a ordem do código-fonte, documentar isso nos comentários da classe seria uma boa coisa. Seu colega pode até ler.
Fletch de

7

As outras respostas são boas, mas não comente sobre isso:

"É uma regra ou não é garantido que não seja alterado nas próximas versões do Jdk?"

Não acredito que existam garantias sobre JDKs futuros, então você nem deve se preocupar com elas. Não haveria nenhuma maneira de aplicá-los, futuros leads de JDK podem simplesmente decidir renegar tais garantias. É como o sistema de parlamento de Westminster: "Nenhum parlamento pode vincular um futuro parlamento."

Dito isso, a história do JDK revela excelente consistência. Eles não fazem muitas alterações significativas, portanto, você pode ter certeza de que o comportamento atual especificado (não apenas observado) será preservado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.